mercurial/util.py
branchstable
changeset 15937 7ed056f1e97d
parent 15720 3bcfea777efc
child 16360 e5788269741a
equal deleted inserted replaced
15900:29defa7d20f6 15937:7ed056f1e97d
    75 unlinkpath = platform.unlinkpath
    75 unlinkpath = platform.unlinkpath
    76 username = platform.username
    76 username = platform.username
    77 
    77 
    78 # Python compatibility
    78 # Python compatibility
    79 
    79 
       
    80 _notset = object()
       
    81 
       
    82 def safehasattr(thing, attr):
       
    83     return getattr(thing, attr, _notset) is not _notset
       
    84 
    80 def sha1(s=''):
    85 def sha1(s=''):
    81     '''
    86     '''
    82     Low-overhead wrapper around Python's SHA support
    87     Low-overhead wrapper around Python's SHA support
    83 
    88 
    84     >>> f = _fastsha1
    89     >>> f = _fastsha1
    87     >>> a.hexdigest()
    92     >>> a.hexdigest()
    88     'da39a3ee5e6b4b0d3255bfef95601890afd80709'
    93     'da39a3ee5e6b4b0d3255bfef95601890afd80709'
    89     '''
    94     '''
    90 
    95 
    91     return _fastsha1(s)
    96     return _fastsha1(s)
    92 
       
    93 _notset = object()
       
    94 def safehasattr(thing, attr):
       
    95     return getattr(thing, attr, _notset) is not _notset
       
    96 
    97 
    97 def _fastsha1(s=''):
    98 def _fastsha1(s=''):
    98     # This function will import sha1 from hashlib or sha (whichever is
    99     # This function will import sha1 from hashlib or sha (whichever is
    99     # available) and overwrite itself with it on the first call.
   100     # available) and overwrite itself with it on the first call.
   100     # Subsequent calls will go directly to the imported function.
   101     # Subsequent calls will go directly to the imported function.
   104         from sha import sha as _sha1
   105         from sha import sha as _sha1
   105     global _fastsha1, sha1
   106     global _fastsha1, sha1
   106     _fastsha1 = sha1 = _sha1
   107     _fastsha1 = sha1 = _sha1
   107     return _sha1(s)
   108     return _sha1(s)
   108 
   109 
   109 import __builtin__
       
   110 
       
   111 if sys.version_info[0] < 3:
       
   112     def fakebuffer(sliceable, offset=0):
       
   113         return sliceable[offset:]
       
   114 else:
       
   115     def fakebuffer(sliceable, offset=0):
       
   116         return memoryview(sliceable)[offset:]
       
   117 try:
   110 try:
   118     buffer
   111     buffer = buffer
   119 except NameError:
   112 except NameError:
   120     __builtin__.buffer = fakebuffer
   113     if sys.version_info[0] < 3:
       
   114         def buffer(sliceable, offset=0):
       
   115             return sliceable[offset:]
       
   116     else:
       
   117         def buffer(sliceable, offset=0):
       
   118             return memoryview(sliceable)[offset:]
   121 
   119 
   122 import subprocess
   120 import subprocess
   123 closefds = os.name == 'posix'
   121 closefds = os.name == 'posix'
   124 
   122 
   125 def popen2(cmd, env=None, newlines=False):
   123 def popen2(cmd, env=None, newlines=False):
   614 
   612 
   615 _fspathcache = {}
   613 _fspathcache = {}
   616 def fspath(name, root):
   614 def fspath(name, root):
   617     '''Get name in the case stored in the filesystem
   615     '''Get name in the case stored in the filesystem
   618 
   616 
   619     The name is either relative to root, or it is an absolute path starting
   617     The name should be relative to root, and be normcase-ed for efficiency.
   620     with root. Note that this function is unnecessary, and should not be
   618 
       
   619     Note that this function is unnecessary, and should not be
   621     called, for case-sensitive filesystems (simply because it's expensive).
   620     called, for case-sensitive filesystems (simply because it's expensive).
   622 
   621 
   623     Both name and root should be normcase-ed.
   622     The root should be normcase-ed, too.
   624     '''
   623     '''
   625     # If name is absolute, make it relative
   624     def find(p, contents):
   626     if name.startswith(root):
   625         for n in contents:
   627         l = len(root)
   626             if normcase(n) == p:
   628         if name[l] == os.sep or name[l] == os.altsep:
   627                 return n
   629             l = l + 1
       
   630         name = name[l:]
       
   631 
       
   632     if not os.path.lexists(os.path.join(root, name)):
       
   633         return None
   628         return None
   634 
   629 
   635     seps = os.sep
   630     seps = os.sep
   636     if os.altsep:
   631     if os.altsep:
   637         seps = seps + os.altsep
   632         seps = seps + os.altsep
   647 
   642 
   648         if dir not in _fspathcache:
   643         if dir not in _fspathcache:
   649             _fspathcache[dir] = os.listdir(dir)
   644             _fspathcache[dir] = os.listdir(dir)
   650         contents = _fspathcache[dir]
   645         contents = _fspathcache[dir]
   651 
   646 
   652         lenp = len(part)
   647         found = find(part, contents)
   653         for n in contents:
   648         if not found:
   654             if lenp == len(n) and normcase(n) == part:
   649             # retry "once per directory" per "dirstate.walk" which
   655                 result.append(n)
   650             # may take place for each patches of "hg qpush", for example
   656                 break
   651             contents = os.listdir(dir)
   657         else:
   652             _fspathcache[dir] = contents
   658             # Cannot happen, as the file exists!
   653             found = find(part, contents)
   659             result.append(part)
   654 
       
   655         result.append(found or part)
   660         dir = os.path.join(dir, part)
   656         dir = os.path.join(dir, part)
   661 
   657 
   662     return ''.join(result)
   658     return ''.join(result)
   663 
   659 
   664 def checknlink(testfile):
   660 def checknlink(testfile):
  1500     >>> url('http://host/a?b#c', parsequery=False, parsefragment=False)
  1496     >>> url('http://host/a?b#c', parsequery=False, parsefragment=False)
  1501     <url scheme: 'http', host: 'host', path: 'a?b#c'>
  1497     <url scheme: 'http', host: 'host', path: 'a?b#c'>
  1502     """
  1498     """
  1503 
  1499 
  1504     _safechars = "!~*'()+"
  1500     _safechars = "!~*'()+"
  1505     _safepchars = "/!~*'()+"
  1501     _safepchars = "/!~*'()+:"
  1506     _matchscheme = re.compile(r'^[a-zA-Z0-9+.\-]+:').match
  1502     _matchscheme = re.compile(r'^[a-zA-Z0-9+.\-]+:').match
  1507 
  1503 
  1508     def __init__(self, path, parsequery=True, parsefragment=True):
  1504     def __init__(self, path, parsequery=True, parsefragment=True):
  1509         # We slowly chomp away at path until we have only the path left
  1505         # We slowly chomp away at path until we have only the path left
  1510         self.scheme = self.user = self.passwd = self.host = None
  1506         self.scheme = self.user = self.passwd = self.host = None
  1612     def __str__(self):
  1608     def __str__(self):
  1613         r"""Join the URL's components back into a URL string.
  1609         r"""Join the URL's components back into a URL string.
  1614 
  1610 
  1615         Examples:
  1611         Examples:
  1616 
  1612 
  1617         >>> str(url('http://user:pw@host:80/?foo#bar'))
  1613         >>> str(url('http://user:pw@host:80/c:/bob?fo:oo#ba:ar'))
  1618         'http://user:pw@host:80/?foo#bar'
  1614         'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'
  1619         >>> str(url('http://user:pw@host:80/?foo=bar&baz=42'))
  1615         >>> str(url('http://user:pw@host:80/?foo=bar&baz=42'))
  1620         'http://user:pw@host:80/?foo=bar&baz=42'
  1616         'http://user:pw@host:80/?foo=bar&baz=42'
  1621         >>> str(url('http://user:pw@host:80/?foo=bar%3dbaz'))
  1617         >>> str(url('http://user:pw@host:80/?foo=bar%3dbaz'))
  1622         'http://user:pw@host:80/?foo=bar%3dbaz'
  1618         'http://user:pw@host:80/?foo=bar%3dbaz'
  1623         >>> str(url('ssh://user:pw@[::1]:2200//home/joe#'))
  1619         >>> str(url('ssh://user:pw@[::1]:2200//home/joe#'))
  1635         >>> str(url('path'))
  1631         >>> str(url('path'))
  1636         'path'
  1632         'path'
  1637         >>> str(url('file:///tmp/foo/bar'))
  1633         >>> str(url('file:///tmp/foo/bar'))
  1638         'file:///tmp/foo/bar'
  1634         'file:///tmp/foo/bar'
  1639         >>> str(url('file:///c:/tmp/foo/bar'))
  1635         >>> str(url('file:///c:/tmp/foo/bar'))
  1640         'file:///c%3A/tmp/foo/bar'
  1636         'file:///c:/tmp/foo/bar'
  1641         >>> print url(r'bundle:foo\bar')
  1637         >>> print url(r'bundle:foo\bar')
  1642         bundle:foo\bar
  1638         bundle:foo\bar
  1643         """
  1639         """
  1644         if self._localpath:
  1640         if self._localpath:
  1645             s = self.path
  1641             s = self.path