##// END OF EJS Templates
windows: fix pyflakes warning on unused imports...
Matt Mackall -
r15016:871c77e7 default
parent child Browse files
Show More
@@ -1,313 +1,314 b''
1 # windows.py - Windows utility function implementations for Mercurial
1 # windows.py - Windows utility function implementations for Mercurial
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2005-2009 Matt Mackall <mpm@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 i18n import _
8 from i18n import _
9 import osutil
9 import osutil
10 import errno, msvcrt, os, re, sys
10 import errno, msvcrt, os, re, sys
11
11
12 from win32 import executablepath
12 import win32
13 from win32 import getuser
13 executablepath = win32.executablepath
14 from win32 import hidewindow
14 getuser = win32.getuser
15 from win32 import lookupreg
15 hidewindow = win32.hidewindow
16 from win32 import makedir
16 lookupreg = win32.lookupreg
17 from win32 import nlinks
17 makedir = win32.makedir
18 from win32 import oslink
18 nlinks = win32.nlinks
19 from win32 import samedevice
19 oslink = win32.oslink
20 from win32 import samefile
20 samedevice = win32.samedevice
21 from win32 import setsignalhandler
21 samefile = win32.samefile
22 from win32 import spawndetached
22 setsignalhandler = win32.setsignalhandler
23 from win32 import termwidth
23 spawndetached = win32.spawndetached
24 from win32 import testpid
24 termwidth = win32.termwidth
25 from win32 import unlink
25 testpid = win32.testpid
26 unlink = win32.unlink
26
27
27 nulldev = 'NUL:'
28 nulldev = 'NUL:'
28 umask = 002
29 umask = 002
29
30
30 # wrap osutil.posixfile to provide friendlier exceptions
31 # wrap osutil.posixfile to provide friendlier exceptions
31 def posixfile(name, mode='r', buffering=-1):
32 def posixfile(name, mode='r', buffering=-1):
32 try:
33 try:
33 return osutil.posixfile(name, mode, buffering)
34 return osutil.posixfile(name, mode, buffering)
34 except WindowsError, err:
35 except WindowsError, err:
35 raise IOError(err.errno, '%s: %s' % (name, err.strerror))
36 raise IOError(err.errno, '%s: %s' % (name, err.strerror))
36 posixfile.__doc__ = osutil.posixfile.__doc__
37 posixfile.__doc__ = osutil.posixfile.__doc__
37
38
38 class winstdout(object):
39 class winstdout(object):
39 '''stdout on windows misbehaves if sent through a pipe'''
40 '''stdout on windows misbehaves if sent through a pipe'''
40
41
41 def __init__(self, fp):
42 def __init__(self, fp):
42 self.fp = fp
43 self.fp = fp
43
44
44 def __getattr__(self, key):
45 def __getattr__(self, key):
45 return getattr(self.fp, key)
46 return getattr(self.fp, key)
46
47
47 def close(self):
48 def close(self):
48 try:
49 try:
49 self.fp.close()
50 self.fp.close()
50 except IOError:
51 except IOError:
51 pass
52 pass
52
53
53 def write(self, s):
54 def write(self, s):
54 try:
55 try:
55 # This is workaround for "Not enough space" error on
56 # This is workaround for "Not enough space" error on
56 # writing large size of data to console.
57 # writing large size of data to console.
57 limit = 16000
58 limit = 16000
58 l = len(s)
59 l = len(s)
59 start = 0
60 start = 0
60 self.softspace = 0
61 self.softspace = 0
61 while start < l:
62 while start < l:
62 end = start + limit
63 end = start + limit
63 self.fp.write(s[start:end])
64 self.fp.write(s[start:end])
64 start = end
65 start = end
65 except IOError, inst:
66 except IOError, inst:
66 if inst.errno != 0:
67 if inst.errno != 0:
67 raise
68 raise
68 self.close()
69 self.close()
69 raise IOError(errno.EPIPE, 'Broken pipe')
70 raise IOError(errno.EPIPE, 'Broken pipe')
70
71
71 def flush(self):
72 def flush(self):
72 try:
73 try:
73 return self.fp.flush()
74 return self.fp.flush()
74 except IOError, inst:
75 except IOError, inst:
75 if inst.errno != errno.EINVAL:
76 if inst.errno != errno.EINVAL:
76 raise
77 raise
77 self.close()
78 self.close()
78 raise IOError(errno.EPIPE, 'Broken pipe')
79 raise IOError(errno.EPIPE, 'Broken pipe')
79
80
80 sys.__stdout__ = sys.stdout = winstdout(sys.stdout)
81 sys.__stdout__ = sys.stdout = winstdout(sys.stdout)
81
82
82 def _is_win_9x():
83 def _is_win_9x():
83 '''return true if run on windows 95, 98 or me.'''
84 '''return true if run on windows 95, 98 or me.'''
84 try:
85 try:
85 return sys.getwindowsversion()[3] == 1
86 return sys.getwindowsversion()[3] == 1
86 except AttributeError:
87 except AttributeError:
87 return 'command' in os.environ.get('comspec', '')
88 return 'command' in os.environ.get('comspec', '')
88
89
89 def openhardlinks():
90 def openhardlinks():
90 return not _is_win_9x()
91 return not _is_win_9x()
91
92
92 def parsepatchoutput(output_line):
93 def parsepatchoutput(output_line):
93 """parses the output produced by patch and returns the filename"""
94 """parses the output produced by patch and returns the filename"""
94 pf = output_line[14:]
95 pf = output_line[14:]
95 if pf[0] == '`':
96 if pf[0] == '`':
96 pf = pf[1:-1] # Remove the quotes
97 pf = pf[1:-1] # Remove the quotes
97 return pf
98 return pf
98
99
99 def sshargs(sshcmd, host, user, port):
100 def sshargs(sshcmd, host, user, port):
100 '''Build argument list for ssh or Plink'''
101 '''Build argument list for ssh or Plink'''
101 pflag = 'plink' in sshcmd.lower() and '-P' or '-p'
102 pflag = 'plink' in sshcmd.lower() and '-P' or '-p'
102 args = user and ("%s@%s" % (user, host)) or host
103 args = user and ("%s@%s" % (user, host)) or host
103 return port and ("%s %s %s" % (args, pflag, port)) or args
104 return port and ("%s %s %s" % (args, pflag, port)) or args
104
105
105 def setflags(f, l, x):
106 def setflags(f, l, x):
106 pass
107 pass
107
108
108 def copymode(src, dst, mode=None):
109 def copymode(src, dst, mode=None):
109 pass
110 pass
110
111
111 def checkexec(path):
112 def checkexec(path):
112 return False
113 return False
113
114
114 def checklink(path):
115 def checklink(path):
115 return False
116 return False
116
117
117 def setbinary(fd):
118 def setbinary(fd):
118 # When run without console, pipes may expose invalid
119 # When run without console, pipes may expose invalid
119 # fileno(), usually set to -1.
120 # fileno(), usually set to -1.
120 fno = getattr(fd, 'fileno', None)
121 fno = getattr(fd, 'fileno', None)
121 if fno is not None and fno() >= 0:
122 if fno is not None and fno() >= 0:
122 msvcrt.setmode(fno(), os.O_BINARY)
123 msvcrt.setmode(fno(), os.O_BINARY)
123
124
124 def pconvert(path):
125 def pconvert(path):
125 return '/'.join(path.split(os.sep))
126 return '/'.join(path.split(os.sep))
126
127
127 def localpath(path):
128 def localpath(path):
128 return path.replace('/', '\\')
129 return path.replace('/', '\\')
129
130
130 def normpath(path):
131 def normpath(path):
131 return pconvert(os.path.normpath(path))
132 return pconvert(os.path.normpath(path))
132
133
133 def realpath(path):
134 def realpath(path):
134 '''
135 '''
135 Returns the true, canonical file system path equivalent to the given
136 Returns the true, canonical file system path equivalent to the given
136 path.
137 path.
137 '''
138 '''
138 # TODO: There may be a more clever way to do this that also handles other,
139 # TODO: There may be a more clever way to do this that also handles other,
139 # less common file systems.
140 # less common file systems.
140 return os.path.normpath(os.path.normcase(os.path.realpath(path)))
141 return os.path.normpath(os.path.normcase(os.path.realpath(path)))
141
142
142 def samestat(s1, s2):
143 def samestat(s1, s2):
143 return False
144 return False
144
145
145 # A sequence of backslashes is special iff it precedes a double quote:
146 # A sequence of backslashes is special iff it precedes a double quote:
146 # - if there's an even number of backslashes, the double quote is not
147 # - if there's an even number of backslashes, the double quote is not
147 # quoted (i.e. it ends the quoted region)
148 # quoted (i.e. it ends the quoted region)
148 # - if there's an odd number of backslashes, the double quote is quoted
149 # - if there's an odd number of backslashes, the double quote is quoted
149 # - in both cases, every pair of backslashes is unquoted into a single
150 # - in both cases, every pair of backslashes is unquoted into a single
150 # backslash
151 # backslash
151 # (See http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx )
152 # (See http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx )
152 # So, to quote a string, we must surround it in double quotes, double
153 # So, to quote a string, we must surround it in double quotes, double
153 # the number of backslashes that preceed double quotes and add another
154 # the number of backslashes that preceed double quotes and add another
154 # backslash before every double quote (being careful with the double
155 # backslash before every double quote (being careful with the double
155 # quote we've appended to the end)
156 # quote we've appended to the end)
156 _quotere = None
157 _quotere = None
157 def shellquote(s):
158 def shellquote(s):
158 global _quotere
159 global _quotere
159 if _quotere is None:
160 if _quotere is None:
160 _quotere = re.compile(r'(\\*)("|\\$)')
161 _quotere = re.compile(r'(\\*)("|\\$)')
161 return '"%s"' % _quotere.sub(r'\1\1\\\2', s)
162 return '"%s"' % _quotere.sub(r'\1\1\\\2', s)
162
163
163 def quotecommand(cmd):
164 def quotecommand(cmd):
164 """Build a command string suitable for os.popen* calls."""
165 """Build a command string suitable for os.popen* calls."""
165 if sys.version_info < (2, 7, 1):
166 if sys.version_info < (2, 7, 1):
166 # Python versions since 2.7.1 do this extra quoting themselves
167 # Python versions since 2.7.1 do this extra quoting themselves
167 return '"' + cmd + '"'
168 return '"' + cmd + '"'
168 return cmd
169 return cmd
169
170
170 def popen(command, mode='r'):
171 def popen(command, mode='r'):
171 # Work around "popen spawned process may not write to stdout
172 # Work around "popen spawned process may not write to stdout
172 # under windows"
173 # under windows"
173 # http://bugs.python.org/issue1366
174 # http://bugs.python.org/issue1366
174 command += " 2> %s" % nulldev
175 command += " 2> %s" % nulldev
175 return os.popen(quotecommand(command), mode)
176 return os.popen(quotecommand(command), mode)
176
177
177 def explainexit(code):
178 def explainexit(code):
178 return _("exited with status %d") % code, code
179 return _("exited with status %d") % code, code
179
180
180 # if you change this stub into a real check, please try to implement the
181 # if you change this stub into a real check, please try to implement the
181 # username and groupname functions above, too.
182 # username and groupname functions above, too.
182 def isowner(st):
183 def isowner(st):
183 return True
184 return True
184
185
185 def findexe(command):
186 def findexe(command):
186 '''Find executable for command searching like cmd.exe does.
187 '''Find executable for command searching like cmd.exe does.
187 If command is a basename then PATH is searched for command.
188 If command is a basename then PATH is searched for command.
188 PATH isn't searched if command is an absolute or relative path.
189 PATH isn't searched if command is an absolute or relative path.
189 An extension from PATHEXT is found and added if not present.
190 An extension from PATHEXT is found and added if not present.
190 If command isn't found None is returned.'''
191 If command isn't found None is returned.'''
191 pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD')
192 pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD')
192 pathexts = [ext for ext in pathext.lower().split(os.pathsep)]
193 pathexts = [ext for ext in pathext.lower().split(os.pathsep)]
193 if os.path.splitext(command)[1].lower() in pathexts:
194 if os.path.splitext(command)[1].lower() in pathexts:
194 pathexts = ['']
195 pathexts = ['']
195
196
196 def findexisting(pathcommand):
197 def findexisting(pathcommand):
197 'Will append extension (if needed) and return existing file'
198 'Will append extension (if needed) and return existing file'
198 for ext in pathexts:
199 for ext in pathexts:
199 executable = pathcommand + ext
200 executable = pathcommand + ext
200 if os.path.exists(executable):
201 if os.path.exists(executable):
201 return executable
202 return executable
202 return None
203 return None
203
204
204 if os.sep in command:
205 if os.sep in command:
205 return findexisting(command)
206 return findexisting(command)
206
207
207 for path in os.environ.get('PATH', '').split(os.pathsep):
208 for path in os.environ.get('PATH', '').split(os.pathsep):
208 executable = findexisting(os.path.join(path, command))
209 executable = findexisting(os.path.join(path, command))
209 if executable is not None:
210 if executable is not None:
210 return executable
211 return executable
211 return findexisting(os.path.expanduser(os.path.expandvars(command)))
212 return findexisting(os.path.expanduser(os.path.expandvars(command)))
212
213
213 def statfiles(files):
214 def statfiles(files):
214 '''Stat each file in files and yield stat or None if file does not exist.
215 '''Stat each file in files and yield stat or None if file does not exist.
215 Cluster and cache stat per directory to minimize number of OS stat calls.'''
216 Cluster and cache stat per directory to minimize number of OS stat calls.'''
216 ncase = os.path.normcase
217 ncase = os.path.normcase
217 dircache = {} # dirname -> filename -> status | None if file does not exist
218 dircache = {} # dirname -> filename -> status | None if file does not exist
218 for nf in files:
219 for nf in files:
219 nf = ncase(nf)
220 nf = ncase(nf)
220 dir, base = os.path.split(nf)
221 dir, base = os.path.split(nf)
221 if not dir:
222 if not dir:
222 dir = '.'
223 dir = '.'
223 cache = dircache.get(dir, None)
224 cache = dircache.get(dir, None)
224 if cache is None:
225 if cache is None:
225 try:
226 try:
226 dmap = dict([(ncase(n), s)
227 dmap = dict([(ncase(n), s)
227 for n, k, s in osutil.listdir(dir, True)])
228 for n, k, s in osutil.listdir(dir, True)])
228 except OSError, err:
229 except OSError, err:
229 # handle directory not found in Python version prior to 2.5
230 # handle directory not found in Python version prior to 2.5
230 # Python <= 2.4 returns native Windows code 3 in errno
231 # Python <= 2.4 returns native Windows code 3 in errno
231 # Python >= 2.5 returns ENOENT and adds winerror field
232 # Python >= 2.5 returns ENOENT and adds winerror field
232 # EINVAL is raised if dir is not a directory.
233 # EINVAL is raised if dir is not a directory.
233 if err.errno not in (3, errno.ENOENT, errno.EINVAL,
234 if err.errno not in (3, errno.ENOENT, errno.EINVAL,
234 errno.ENOTDIR):
235 errno.ENOTDIR):
235 raise
236 raise
236 dmap = {}
237 dmap = {}
237 cache = dircache.setdefault(dir, dmap)
238 cache = dircache.setdefault(dir, dmap)
238 yield cache.get(base, None)
239 yield cache.get(base, None)
239
240
240 def username(uid=None):
241 def username(uid=None):
241 """Return the name of the user with the given uid.
242 """Return the name of the user with the given uid.
242
243
243 If uid is None, return the name of the current user."""
244 If uid is None, return the name of the current user."""
244 return None
245 return None
245
246
246 def groupname(gid=None):
247 def groupname(gid=None):
247 """Return the name of the group with the given gid.
248 """Return the name of the group with the given gid.
248
249
249 If gid is None, return the name of the current group."""
250 If gid is None, return the name of the current group."""
250 return None
251 return None
251
252
252 def _removedirs(name):
253 def _removedirs(name):
253 """special version of os.removedirs that does not remove symlinked
254 """special version of os.removedirs that does not remove symlinked
254 directories or junction points if they actually contain files"""
255 directories or junction points if they actually contain files"""
255 if osutil.listdir(name):
256 if osutil.listdir(name):
256 return
257 return
257 os.rmdir(name)
258 os.rmdir(name)
258 head, tail = os.path.split(name)
259 head, tail = os.path.split(name)
259 if not tail:
260 if not tail:
260 head, tail = os.path.split(head)
261 head, tail = os.path.split(head)
261 while head and tail:
262 while head and tail:
262 try:
263 try:
263 if osutil.listdir(head):
264 if osutil.listdir(head):
264 return
265 return
265 os.rmdir(head)
266 os.rmdir(head)
266 except (ValueError, OSError):
267 except (ValueError, OSError):
267 break
268 break
268 head, tail = os.path.split(head)
269 head, tail = os.path.split(head)
269
270
270 def unlinkpath(f):
271 def unlinkpath(f):
271 """unlink and remove the directory if it is empty"""
272 """unlink and remove the directory if it is empty"""
272 unlink(f)
273 unlink(f)
273 # try removing directories that might now be empty
274 # try removing directories that might now be empty
274 try:
275 try:
275 _removedirs(os.path.dirname(f))
276 _removedirs(os.path.dirname(f))
276 except OSError:
277 except OSError:
277 pass
278 pass
278
279
279 def rename(src, dst):
280 def rename(src, dst):
280 '''atomically rename file src to dst, replacing dst if it exists'''
281 '''atomically rename file src to dst, replacing dst if it exists'''
281 try:
282 try:
282 os.rename(src, dst)
283 os.rename(src, dst)
283 except OSError, e:
284 except OSError, e:
284 if e.errno != errno.EEXIST:
285 if e.errno != errno.EEXIST:
285 raise
286 raise
286 unlink(dst)
287 unlink(dst)
287 os.rename(src, dst)
288 os.rename(src, dst)
288
289
289 def gethgcmd():
290 def gethgcmd():
290 return [sys.executable] + sys.argv[:1]
291 return [sys.executable] + sys.argv[:1]
291
292
292 def termwidth():
293 def termwidth():
293 # cmd.exe does not handle CR like a unix console, the CR is
294 # cmd.exe does not handle CR like a unix console, the CR is
294 # counted in the line length. On 80 columns consoles, if 80
295 # counted in the line length. On 80 columns consoles, if 80
295 # characters are written, the following CR won't apply on the
296 # characters are written, the following CR won't apply on the
296 # current line but on the new one. Keep room for it.
297 # current line but on the new one. Keep room for it.
297 return 79
298 return 79
298
299
299 def groupmembers(name):
300 def groupmembers(name):
300 # Don't support groups on Windows for now
301 # Don't support groups on Windows for now
301 raise KeyError()
302 raise KeyError()
302
303
303 def isexec(f):
304 def isexec(f):
304 return False
305 return False
305
306
306 class cachestat(object):
307 class cachestat(object):
307 def __init__(self, path):
308 def __init__(self, path):
308 pass
309 pass
309
310
310 def cacheable(self):
311 def cacheable(self):
311 return False
312 return False
312
313
313 expandglobs = True
314 expandglobs = True
General Comments 0
You need to be logged in to leave comments. Login now