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