3 # Copyright 2005-2009 Olivia Mackall <olivia@selenic.com> and others |
3 # Copyright 2005-2009 Olivia Mackall <olivia@selenic.com> and others |
4 # |
4 # |
5 # This software may be used and distributed according to the terms of the |
5 # This software may be used and distributed according to the terms of the |
6 # GNU General Public License version 2 or any later version. |
6 # GNU General Public License version 2 or any later version. |
7 |
7 |
8 from __future__ import absolute_import |
|
9 |
8 |
10 import errno |
9 import errno |
11 import getpass |
10 import getpass |
12 import msvcrt |
11 import msvcrt # pytype: disable=import-error |
13 import os |
12 import os |
14 import re |
13 import re |
15 import stat |
14 import stat |
16 import string |
15 import string |
17 import sys |
16 import sys |
|
17 import winreg # pytype: disable=import-error |
18 |
18 |
19 from .i18n import _ |
19 from .i18n import _ |
20 from .pycompat import getattr |
20 from .pycompat import getattr |
21 from . import ( |
21 from . import ( |
22 encoding, |
22 encoding, |
52 unlink = win32.unlink |
45 unlink = win32.unlink |
53 |
46 |
54 umask = 0o022 |
47 umask = 0o022 |
55 |
48 |
56 |
49 |
57 class mixedfilemodewrapper(object): |
50 class mixedfilemodewrapper: |
58 """Wraps a file handle when it is opened in read/write mode. |
51 """Wraps a file handle when it is opened in read/write mode. |
59 |
52 |
60 fopen() and fdopen() on Windows have a specific-to-Windows requirement |
53 fopen() and fdopen() on Windows have a specific-to-Windows requirement |
61 that files opened with mode r+, w+, or a+ make a call to a file positioning |
54 that files opened with mode r+, w+, or a+ make a call to a file positioning |
62 function when switching between reads and writes. Without this extra call, |
55 function when switching between reads and writes. Without this extra call, |
129 |
122 |
130 object.__setattr__(self, '_lastop', self.OPREAD) |
123 object.__setattr__(self, '_lastop', self.OPREAD) |
131 return self._fp.readlines(*args, **kwargs) |
124 return self._fp.readlines(*args, **kwargs) |
132 |
125 |
133 |
126 |
134 class fdproxy(object): |
127 class fdproxy: |
135 """Wraps osutil.posixfile() to override the name attribute to reflect the |
128 """Wraps osutil.posixfile() to override the name attribute to reflect the |
136 underlying file name. |
129 underlying file name. |
137 """ |
130 """ |
138 |
131 |
139 def __init__(self, name, fp): |
132 def __init__(self, name, fp): |
161 try: |
154 try: |
162 fp = osutil.posixfile(name, mode, buffering) # may raise WindowsError |
155 fp = osutil.posixfile(name, mode, buffering) # may raise WindowsError |
163 |
156 |
164 # PyFile_FromFd() ignores the name, and seems to report fp.name as the |
157 # PyFile_FromFd() ignores the name, and seems to report fp.name as the |
165 # underlying file descriptor. |
158 # underlying file descriptor. |
166 if pycompat.ispy3: |
159 fp = fdproxy(name, fp) |
167 fp = fdproxy(name, fp) |
|
168 |
160 |
169 # The position when opening in append mode is implementation defined, so |
161 # The position when opening in append mode is implementation defined, so |
170 # make it consistent with other platforms, which position at EOF. |
162 # make it consistent with other platforms, which position at EOF. |
171 if b'a' in mode: |
163 if b'a' in mode: |
172 fp.seek(0, os.SEEK_END) |
164 fp.seek(0, os.SEEK_END) |
214 msvcrt.putwch(u'\r') # pytype: disable=module-attr |
206 msvcrt.putwch(u'\r') # pytype: disable=module-attr |
215 msvcrt.putwch(u'\n') # pytype: disable=module-attr |
207 msvcrt.putwch(u'\n') # pytype: disable=module-attr |
216 return encoding.unitolocal(pw) |
208 return encoding.unitolocal(pw) |
217 |
209 |
218 |
210 |
219 class winstdout(object): |
211 class winstdout: |
220 """Some files on Windows misbehave. |
212 """Some files on Windows misbehave. |
221 |
213 |
222 When writing to a broken pipe, EINVAL instead of EPIPE may be raised. |
214 When writing to a broken pipe, EINVAL instead of EPIPE may be raised. |
223 |
215 |
224 When writing too many bytes to a console at the same, a "Not enough space" |
216 When writing too many bytes to a console at the same, a "Not enough space" |
225 error may happen. Python 3 already works around that. |
217 error may happen. Python 3 already works around that. |
226 """ |
218 """ |
227 |
219 |
228 def __init__(self, fp): |
220 def __init__(self, fp): |
229 self.fp = fp |
221 self.fp = fp |
230 self.throttle = not pycompat.ispy3 and _isatty(fp) |
|
231 |
222 |
232 def __getattr__(self, key): |
223 def __getattr__(self, key): |
233 return getattr(self.fp, key) |
224 return getattr(self.fp, key) |
234 |
225 |
235 def close(self): |
226 def close(self): |
238 except IOError: |
229 except IOError: |
239 pass |
230 pass |
240 |
231 |
241 def write(self, s): |
232 def write(self, s): |
242 try: |
233 try: |
243 if not self.throttle: |
234 return self.fp.write(s) |
244 return self.fp.write(s) |
|
245 # This is workaround for "Not enough space" error on |
|
246 # writing large size of data to console. |
|
247 limit = 16000 |
|
248 l = len(s) |
|
249 start = 0 |
|
250 while start < l: |
|
251 end = start + limit |
|
252 self.fp.write(s[start:end]) |
|
253 start = end |
|
254 except IOError as inst: |
235 except IOError as inst: |
255 if inst.errno != 0 and not win32.lasterrorwaspipeerror(inst): |
236 if inst.errno != 0 and not win32.lasterrorwaspipeerror(inst): |
256 raise |
237 raise |
257 self.close() |
238 self.close() |
258 raise IOError(errno.EPIPE, 'Broken pipe') |
239 raise IOError(errno.EPIPE, 'Broken pipe') |
587 dmap = { |
568 dmap = { |
588 normcase(n): s |
569 normcase(n): s |
589 for n, k, s in listdir(dir, True) |
570 for n, k, s in listdir(dir, True) |
590 if getkind(s.st_mode) in _wantedkinds |
571 if getkind(s.st_mode) in _wantedkinds |
591 } |
572 } |
592 except OSError as err: |
573 except (FileNotFoundError, NotADirectoryError): |
593 # Python >= 2.5 returns ENOENT and adds winerror field |
|
594 # EINVAL is raised if dir is not a directory. |
|
595 if err.errno not in (errno.ENOENT, errno.EINVAL, errno.ENOTDIR): |
|
596 raise |
|
597 dmap = {} |
574 dmap = {} |
598 cache = dircache.setdefault(dir, dmap) |
575 cache = dircache.setdefault(dir, dmap) |
599 yield cache.get(base, None) |
576 yield cache.get(base, None) |
600 |
577 |
601 |
578 |
687 scope: optionally specify scope for registry lookup, this can be |
662 scope: optionally specify scope for registry lookup, this can be |
688 a sequence of scopes to look up in order. Default (CURRENT_USER, |
663 a sequence of scopes to look up in order. Default (CURRENT_USER, |
689 LOCAL_MACHINE). |
664 LOCAL_MACHINE). |
690 """ |
665 """ |
691 if scope is None: |
666 if scope is None: |
|
667 # pytype: disable=module-attr |
692 scope = (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE) |
668 scope = (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE) |
|
669 # pytype: enable=module-attr |
693 elif not isinstance(scope, (list, tuple)): |
670 elif not isinstance(scope, (list, tuple)): |
694 scope = (scope,) |
671 scope = (scope,) |
695 for s in scope: |
672 for s in scope: |
696 try: |
673 try: |
|
674 # pytype: disable=module-attr |
697 with winreg.OpenKey(s, encoding.strfromlocal(key)) as hkey: |
675 with winreg.OpenKey(s, encoding.strfromlocal(key)) as hkey: |
698 name = valname and encoding.strfromlocal(valname) or valname |
676 # pytype: enable=module-attr |
|
677 name = None |
|
678 if valname is not None: |
|
679 name = encoding.strfromlocal(valname) |
|
680 # pytype: disable=module-attr |
699 val = winreg.QueryValueEx(hkey, name)[0] |
681 val = winreg.QueryValueEx(hkey, name)[0] |
|
682 # pytype: enable=module-attr |
|
683 |
700 # never let a Unicode string escape into the wild |
684 # never let a Unicode string escape into the wild |
701 return encoding.unitolocal(val) |
685 return encoding.unitolocal(val) |
702 except EnvironmentError: |
686 except EnvironmentError: |
703 pass |
687 pass |
704 |
688 |