equal
deleted
inserted
replaced
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 |