##// END OF EJS Templates
windows: fix import of win32.py (was util_win32.py)
Sune Foldager -
r7932:96501a4a default
parent child Browse files
Show More
@@ -1,253 +1,253 b''
1 """
1 """
2 windows.py - Windows utility function implementations for Mercurial
2 windows.py - Windows utility function implementations for Mercurial
3
3
4 Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
5
5
6 This software may be used and distributed according to the terms of
6 This software may be used and distributed according to the terms of
7 the GNU General Public License version 2, incorporated herein by
7 the GNU General Public License version 2, incorporated herein by
8 reference.
8 reference.
9 """
9 """
10
10
11 from i18n import _
11 from i18n import _
12 import errno, msvcrt, os, osutil, re, sys
12 import errno, msvcrt, os, osutil, re, sys
13 nulldev = 'NUL:'
13 nulldev = 'NUL:'
14
14
15 umask = 002
15 umask = 002
16
16
17 class winstdout:
17 class winstdout:
18 '''stdout on windows misbehaves if sent through a pipe'''
18 '''stdout on windows misbehaves if sent through a pipe'''
19
19
20 def __init__(self, fp):
20 def __init__(self, fp):
21 self.fp = fp
21 self.fp = fp
22
22
23 def __getattr__(self, key):
23 def __getattr__(self, key):
24 return getattr(self.fp, key)
24 return getattr(self.fp, key)
25
25
26 def close(self):
26 def close(self):
27 try:
27 try:
28 self.fp.close()
28 self.fp.close()
29 except: pass
29 except: pass
30
30
31 def write(self, s):
31 def write(self, s):
32 try:
32 try:
33 # This is workaround for "Not enough space" error on
33 # This is workaround for "Not enough space" error on
34 # writing large size of data to console.
34 # writing large size of data to console.
35 limit = 16000
35 limit = 16000
36 l = len(s)
36 l = len(s)
37 start = 0
37 start = 0
38 while start < l:
38 while start < l:
39 end = start + limit
39 end = start + limit
40 self.fp.write(s[start:end])
40 self.fp.write(s[start:end])
41 start = end
41 start = end
42 except IOError, inst:
42 except IOError, inst:
43 if inst.errno != 0: raise
43 if inst.errno != 0: raise
44 self.close()
44 self.close()
45 raise IOError(errno.EPIPE, 'Broken pipe')
45 raise IOError(errno.EPIPE, 'Broken pipe')
46
46
47 def flush(self):
47 def flush(self):
48 try:
48 try:
49 return self.fp.flush()
49 return self.fp.flush()
50 except IOError, inst:
50 except IOError, inst:
51 if inst.errno != errno.EINVAL: raise
51 if inst.errno != errno.EINVAL: raise
52 self.close()
52 self.close()
53 raise IOError(errno.EPIPE, 'Broken pipe')
53 raise IOError(errno.EPIPE, 'Broken pipe')
54
54
55 sys.stdout = winstdout(sys.stdout)
55 sys.stdout = winstdout(sys.stdout)
56
56
57 def _is_win_9x():
57 def _is_win_9x():
58 '''return true if run on windows 95, 98 or me.'''
58 '''return true if run on windows 95, 98 or me.'''
59 try:
59 try:
60 return sys.getwindowsversion()[3] == 1
60 return sys.getwindowsversion()[3] == 1
61 except AttributeError:
61 except AttributeError:
62 return 'command' in os.environ.get('comspec', '')
62 return 'command' in os.environ.get('comspec', '')
63
63
64 def openhardlinks():
64 def openhardlinks():
65 return not _is_win_9x and "win32api" in locals()
65 return not _is_win_9x and "win32api" in locals()
66
66
67 def system_rcpath():
67 def system_rcpath():
68 try:
68 try:
69 return system_rcpath_win32()
69 return system_rcpath_win32()
70 except:
70 except:
71 return [r'c:\mercurial\mercurial.ini']
71 return [r'c:\mercurial\mercurial.ini']
72
72
73 def user_rcpath():
73 def user_rcpath():
74 '''return os-specific hgrc search path to the user dir'''
74 '''return os-specific hgrc search path to the user dir'''
75 try:
75 try:
76 path = user_rcpath_win32()
76 path = user_rcpath_win32()
77 except:
77 except:
78 home = os.path.expanduser('~')
78 home = os.path.expanduser('~')
79 path = [os.path.join(home, 'mercurial.ini'),
79 path = [os.path.join(home, 'mercurial.ini'),
80 os.path.join(home, '.hgrc')]
80 os.path.join(home, '.hgrc')]
81 userprofile = os.environ.get('USERPROFILE')
81 userprofile = os.environ.get('USERPROFILE')
82 if userprofile:
82 if userprofile:
83 path.append(os.path.join(userprofile, 'mercurial.ini'))
83 path.append(os.path.join(userprofile, 'mercurial.ini'))
84 path.append(os.path.join(userprofile, '.hgrc'))
84 path.append(os.path.join(userprofile, '.hgrc'))
85 return path
85 return path
86
86
87 def parse_patch_output(output_line):
87 def parse_patch_output(output_line):
88 """parses the output produced by patch and returns the file name"""
88 """parses the output produced by patch and returns the file name"""
89 pf = output_line[14:]
89 pf = output_line[14:]
90 if pf[0] == '`':
90 if pf[0] == '`':
91 pf = pf[1:-1] # Remove the quotes
91 pf = pf[1:-1] # Remove the quotes
92 return pf
92 return pf
93
93
94 def sshargs(sshcmd, host, user, port):
94 def sshargs(sshcmd, host, user, port):
95 '''Build argument list for ssh or Plink'''
95 '''Build argument list for ssh or Plink'''
96 pflag = 'plink' in sshcmd.lower() and '-P' or '-p'
96 pflag = 'plink' in sshcmd.lower() and '-P' or '-p'
97 args = user and ("%s@%s" % (user, host)) or host
97 args = user and ("%s@%s" % (user, host)) or host
98 return port and ("%s %s %s" % (args, pflag, port)) or args
98 return port and ("%s %s %s" % (args, pflag, port)) or args
99
99
100 def testpid(pid):
100 def testpid(pid):
101 '''return False if pid dead, True if running or not known'''
101 '''return False if pid dead, True if running or not known'''
102 return True
102 return True
103
103
104 def set_flags(f, l, x):
104 def set_flags(f, l, x):
105 pass
105 pass
106
106
107 def set_binary(fd):
107 def set_binary(fd):
108 # When run without console, pipes may expose invalid
108 # When run without console, pipes may expose invalid
109 # fileno(), usually set to -1.
109 # fileno(), usually set to -1.
110 if hasattr(fd, 'fileno') and fd.fileno() >= 0:
110 if hasattr(fd, 'fileno') and fd.fileno() >= 0:
111 msvcrt.setmode(fd.fileno(), os.O_BINARY)
111 msvcrt.setmode(fd.fileno(), os.O_BINARY)
112
112
113 def pconvert(path):
113 def pconvert(path):
114 return '/'.join(path.split(os.sep))
114 return '/'.join(path.split(os.sep))
115
115
116 def localpath(path):
116 def localpath(path):
117 return path.replace('/', '\\')
117 return path.replace('/', '\\')
118
118
119 def normpath(path):
119 def normpath(path):
120 return pconvert(os.path.normpath(path))
120 return pconvert(os.path.normpath(path))
121
121
122 def samestat(s1, s2):
122 def samestat(s1, s2):
123 return False
123 return False
124
124
125 # A sequence of backslashes is special iff it precedes a double quote:
125 # A sequence of backslashes is special iff it precedes a double quote:
126 # - if there's an even number of backslashes, the double quote is not
126 # - if there's an even number of backslashes, the double quote is not
127 # quoted (i.e. it ends the quoted region)
127 # quoted (i.e. it ends the quoted region)
128 # - if there's an odd number of backslashes, the double quote is quoted
128 # - if there's an odd number of backslashes, the double quote is quoted
129 # - in both cases, every pair of backslashes is unquoted into a single
129 # - in both cases, every pair of backslashes is unquoted into a single
130 # backslash
130 # backslash
131 # (See http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx )
131 # (See http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx )
132 # So, to quote a string, we must surround it in double quotes, double
132 # So, to quote a string, we must surround it in double quotes, double
133 # the number of backslashes that preceed double quotes and add another
133 # the number of backslashes that preceed double quotes and add another
134 # backslash before every double quote (being careful with the double
134 # backslash before every double quote (being careful with the double
135 # quote we've appended to the end)
135 # quote we've appended to the end)
136 _quotere = None
136 _quotere = None
137 def shellquote(s):
137 def shellquote(s):
138 global _quotere
138 global _quotere
139 if _quotere is None:
139 if _quotere is None:
140 _quotere = re.compile(r'(\\*)("|\\$)')
140 _quotere = re.compile(r'(\\*)("|\\$)')
141 return '"%s"' % _quotere.sub(r'\1\1\\\2', s)
141 return '"%s"' % _quotere.sub(r'\1\1\\\2', s)
142
142
143 def quotecommand(cmd):
143 def quotecommand(cmd):
144 """Build a command string suitable for os.popen* calls."""
144 """Build a command string suitable for os.popen* calls."""
145 # The extra quotes are needed because popen* runs the command
145 # The extra quotes are needed because popen* runs the command
146 # through the current COMSPEC. cmd.exe suppress enclosing quotes.
146 # through the current COMSPEC. cmd.exe suppress enclosing quotes.
147 return '"' + cmd + '"'
147 return '"' + cmd + '"'
148
148
149 def popen(command, mode='r'):
149 def popen(command, mode='r'):
150 # Work around "popen spawned process may not write to stdout
150 # Work around "popen spawned process may not write to stdout
151 # under windows"
151 # under windows"
152 # http://bugs.python.org/issue1366
152 # http://bugs.python.org/issue1366
153 command += " 2> %s" % nulldev
153 command += " 2> %s" % nulldev
154 return os.popen(quotecommand(command), mode)
154 return os.popen(quotecommand(command), mode)
155
155
156 def explain_exit(code):
156 def explain_exit(code):
157 return _("exited with status %d") % code, code
157 return _("exited with status %d") % code, code
158
158
159 # if you change this stub into a real check, please try to implement the
159 # if you change this stub into a real check, please try to implement the
160 # username and groupname functions above, too.
160 # username and groupname functions above, too.
161 def isowner(fp, st=None):
161 def isowner(fp, st=None):
162 return True
162 return True
163
163
164 def find_exe(command):
164 def find_exe(command):
165 '''Find executable for command searching like cmd.exe does.
165 '''Find executable for command searching like cmd.exe does.
166 If command is a basename then PATH is searched for command.
166 If command is a basename then PATH is searched for command.
167 PATH isn't searched if command is an absolute or relative path.
167 PATH isn't searched if command is an absolute or relative path.
168 An extension from PATHEXT is found and added if not present.
168 An extension from PATHEXT is found and added if not present.
169 If command isn't found None is returned.'''
169 If command isn't found None is returned.'''
170 pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD')
170 pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD')
171 pathexts = [ext for ext in pathext.lower().split(os.pathsep)]
171 pathexts = [ext for ext in pathext.lower().split(os.pathsep)]
172 if os.path.splitext(command)[1].lower() in pathexts:
172 if os.path.splitext(command)[1].lower() in pathexts:
173 pathexts = ['']
173 pathexts = ['']
174
174
175 def findexisting(pathcommand):
175 def findexisting(pathcommand):
176 'Will append extension (if needed) and return existing file'
176 'Will append extension (if needed) and return existing file'
177 for ext in pathexts:
177 for ext in pathexts:
178 executable = pathcommand + ext
178 executable = pathcommand + ext
179 if os.path.exists(executable):
179 if os.path.exists(executable):
180 return executable
180 return executable
181 return None
181 return None
182
182
183 if os.sep in command:
183 if os.sep in command:
184 return findexisting(command)
184 return findexisting(command)
185
185
186 for path in os.environ.get('PATH', '').split(os.pathsep):
186 for path in os.environ.get('PATH', '').split(os.pathsep):
187 executable = findexisting(os.path.join(path, command))
187 executable = findexisting(os.path.join(path, command))
188 if executable is not None:
188 if executable is not None:
189 return executable
189 return executable
190 return None
190 return None
191
191
192 def set_signal_handler():
192 def set_signal_handler():
193 try:
193 try:
194 set_signal_handler_win32()
194 set_signal_handler_win32()
195 except NameError:
195 except NameError:
196 pass
196 pass
197
197
198 def statfiles(files):
198 def statfiles(files):
199 '''Stat each file in files and yield stat or None if file does not exist.
199 '''Stat each file in files and yield stat or None if file does not exist.
200 Cluster and cache stat per directory to minimize number of OS stat calls.'''
200 Cluster and cache stat per directory to minimize number of OS stat calls.'''
201 ncase = os.path.normcase
201 ncase = os.path.normcase
202 sep = os.sep
202 sep = os.sep
203 dircache = {} # dirname -> filename -> status | None if file does not exist
203 dircache = {} # dirname -> filename -> status | None if file does not exist
204 for nf in files:
204 for nf in files:
205 nf = ncase(nf)
205 nf = ncase(nf)
206 pos = nf.rfind(sep)
206 pos = nf.rfind(sep)
207 if pos == -1:
207 if pos == -1:
208 dir, base = '.', nf
208 dir, base = '.', nf
209 else:
209 else:
210 dir, base = nf[:pos+1], nf[pos+1:]
210 dir, base = nf[:pos+1], nf[pos+1:]
211 cache = dircache.get(dir, None)
211 cache = dircache.get(dir, None)
212 if cache is None:
212 if cache is None:
213 try:
213 try:
214 dmap = dict([(ncase(n), s)
214 dmap = dict([(ncase(n), s)
215 for n, k, s in osutil.listdir(dir, True)])
215 for n, k, s in osutil.listdir(dir, True)])
216 except OSError, err:
216 except OSError, err:
217 # handle directory not found in Python version prior to 2.5
217 # handle directory not found in Python version prior to 2.5
218 # Python <= 2.4 returns native Windows code 3 in errno
218 # Python <= 2.4 returns native Windows code 3 in errno
219 # Python >= 2.5 returns ENOENT and adds winerror field
219 # Python >= 2.5 returns ENOENT and adds winerror field
220 # EINVAL is raised if dir is not a directory.
220 # EINVAL is raised if dir is not a directory.
221 if err.errno not in (3, errno.ENOENT, errno.EINVAL,
221 if err.errno not in (3, errno.ENOENT, errno.EINVAL,
222 errno.ENOTDIR):
222 errno.ENOTDIR):
223 raise
223 raise
224 dmap = {}
224 dmap = {}
225 cache = dircache.setdefault(dir, dmap)
225 cache = dircache.setdefault(dir, dmap)
226 yield cache.get(base, None)
226 yield cache.get(base, None)
227
227
228 def getuser():
228 def getuser():
229 '''return name of current user'''
229 '''return name of current user'''
230 raise Abort(_('user name not available - set USERNAME '
230 raise Abort(_('user name not available - set USERNAME '
231 'environment variable'))
231 'environment variable'))
232
232
233 def username(uid=None):
233 def username(uid=None):
234 """Return the name of the user with the given uid.
234 """Return the name of the user with the given uid.
235
235
236 If uid is None, return the name of the current user."""
236 If uid is None, return the name of the current user."""
237 return None
237 return None
238
238
239 def groupname(gid=None):
239 def groupname(gid=None):
240 """Return the name of the group with the given gid.
240 """Return the name of the group with the given gid.
241
241
242 If gid is None, return the name of the current group."""
242 If gid is None, return the name of the current group."""
243 return None
243 return None
244
244
245 posixfile = file
245 posixfile = file
246 try:
246 try:
247 # override functions with win32 versions if possible
247 # override functions with win32 versions if possible
248 from util_win32 import *
248 from win32 import *
249 if not _is_win_9x():
249 if not _is_win_9x():
250 posixfile = posixfile_nt
250 posixfile = posixfile_nt
251 except ImportError:
251 except ImportError:
252 pass
252 pass
253
253
General Comments 0
You need to be logged in to leave comments. Login now