151 |
151 |
152 def __getattr__(self, name): |
152 def __getattr__(self, name): |
153 return getattr(self._fp, name) |
153 return getattr(self._fp, name) |
154 |
154 |
155 |
155 |
156 def posixfile(name, mode='r', buffering=-1): |
156 def posixfile(name, mode=b'r', buffering=-1): |
157 '''Open a file with even more POSIX-like semantics''' |
157 '''Open a file with even more POSIX-like semantics''' |
158 try: |
158 try: |
159 fp = osutil.posixfile(name, mode, buffering) # may raise WindowsError |
159 fp = osutil.posixfile(name, mode, buffering) # may raise WindowsError |
160 |
160 |
161 # PyFile_FromFd() ignores the name, and seems to report fp.name as the |
161 # PyFile_FromFd() ignores the name, and seems to report fp.name as the |
163 if pycompat.ispy3: |
163 if pycompat.ispy3: |
164 fp = fdproxy(name, fp) |
164 fp = fdproxy(name, fp) |
165 |
165 |
166 # The position when opening in append mode is implementation defined, so |
166 # The position when opening in append mode is implementation defined, so |
167 # make it consistent with other platforms, which position at EOF. |
167 # make it consistent with other platforms, which position at EOF. |
168 if 'a' in mode: |
168 if b'a' in mode: |
169 fp.seek(0, os.SEEK_END) |
169 fp.seek(0, os.SEEK_END) |
170 |
170 |
171 if '+' in mode: |
171 if b'+' in mode: |
172 return mixedfilemodewrapper(fp) |
172 return mixedfilemodewrapper(fp) |
173 |
173 |
174 return fp |
174 return fp |
175 except WindowsError as err: |
175 except WindowsError as err: |
176 # convert to a friendlier exception |
176 # convert to a friendlier exception |
228 def _is_win_9x(): |
228 def _is_win_9x(): |
229 '''return true if run on windows 95, 98 or me.''' |
229 '''return true if run on windows 95, 98 or me.''' |
230 try: |
230 try: |
231 return sys.getwindowsversion()[3] == 1 |
231 return sys.getwindowsversion()[3] == 1 |
232 except AttributeError: |
232 except AttributeError: |
233 return 'command' in encoding.environ.get('comspec', '') |
233 return b'command' in encoding.environ.get(b'comspec', b'') |
234 |
234 |
235 |
235 |
236 def openhardlinks(): |
236 def openhardlinks(): |
237 return not _is_win_9x() |
237 return not _is_win_9x() |
238 |
238 |
239 |
239 |
240 def parsepatchoutput(output_line): |
240 def parsepatchoutput(output_line): |
241 """parses the output produced by patch and returns the filename""" |
241 """parses the output produced by patch and returns the filename""" |
242 pf = output_line[14:] |
242 pf = output_line[14:] |
243 if pf[0] == '`': |
243 if pf[0] == b'`': |
244 pf = pf[1:-1] # Remove the quotes |
244 pf = pf[1:-1] # Remove the quotes |
245 return pf |
245 return pf |
246 |
246 |
247 |
247 |
248 def sshargs(sshcmd, host, user, port): |
248 def sshargs(sshcmd, host, user, port): |
249 '''Build argument list for ssh or Plink''' |
249 '''Build argument list for ssh or Plink''' |
250 pflag = 'plink' in sshcmd.lower() and '-P' or '-p' |
250 pflag = b'plink' in sshcmd.lower() and b'-P' or b'-p' |
251 args = user and ("%s@%s" % (user, host)) or host |
251 args = user and (b"%s@%s" % (user, host)) or host |
252 if args.startswith('-') or args.startswith('/'): |
252 if args.startswith(b'-') or args.startswith(b'/'): |
253 raise error.Abort( |
253 raise error.Abort( |
254 _('illegal ssh hostname or username starting with - or /: %s') |
254 _(b'illegal ssh hostname or username starting with - or /: %s') |
255 % args |
255 % args |
256 ) |
256 ) |
257 args = shellquote(args) |
257 args = shellquote(args) |
258 if port: |
258 if port: |
259 args = '%s %s %s' % (pflag, shellquote(port), args) |
259 args = b'%s %s %s' % (pflag, shellquote(port), args) |
260 return args |
260 return args |
261 |
261 |
262 |
262 |
263 def setflags(f, l, x): |
263 def setflags(f, l, x): |
264 pass |
264 pass |
283 if fno is not None and fno() >= 0: |
283 if fno is not None and fno() >= 0: |
284 msvcrt.setmode(fno(), os.O_BINARY) |
284 msvcrt.setmode(fno(), os.O_BINARY) |
285 |
285 |
286 |
286 |
287 def pconvert(path): |
287 def pconvert(path): |
288 return path.replace(pycompat.ossep, '/') |
288 return path.replace(pycompat.ossep, b'/') |
289 |
289 |
290 |
290 |
291 def localpath(path): |
291 def localpath(path): |
292 return path.replace('/', '\\') |
292 return path.replace(b'/', b'\\') |
293 |
293 |
294 |
294 |
295 def normpath(path): |
295 def normpath(path): |
296 return pconvert(os.path.normpath(path)) |
296 return pconvert(os.path.normpath(path)) |
297 |
297 |
405 elif ( |
405 elif ( |
406 c == b'~' |
406 c == b'~' |
407 and index + 1 < pathlen |
407 and index + 1 < pathlen |
408 and path[index + 1 : index + 2] in (b'\\', b'/') |
408 and path[index + 1 : index + 2] in (b'\\', b'/') |
409 ): |
409 ): |
410 res += "%USERPROFILE%" |
410 res += b"%USERPROFILE%" |
411 elif ( |
411 elif ( |
412 c == b'\\' |
412 c == b'\\' |
413 and index + 1 < pathlen |
413 and index + 1 < pathlen |
414 and path[index + 1 : index + 2] in (b'$', b'~') |
414 and path[index + 1 : index + 2] in (b'$', b'~') |
415 ): |
415 ): |
481 |
481 |
482 def quotecommand(cmd): |
482 def quotecommand(cmd): |
483 """Build a command string suitable for os.popen* calls.""" |
483 """Build a command string suitable for os.popen* calls.""" |
484 if sys.version_info < (2, 7, 1): |
484 if sys.version_info < (2, 7, 1): |
485 # Python versions since 2.7.1 do this extra quoting themselves |
485 # Python versions since 2.7.1 do this extra quoting themselves |
486 return '"' + cmd + '"' |
486 return b'"' + cmd + b'"' |
487 return cmd |
487 return cmd |
488 |
488 |
489 |
489 |
490 # if you change this stub into a real check, please try to implement the |
490 # if you change this stub into a real check, please try to implement the |
491 # username and groupname functions above, too. |
491 # username and groupname functions above, too. |
497 '''Find executable for command searching like cmd.exe does. |
497 '''Find executable for command searching like cmd.exe does. |
498 If command is a basename then PATH is searched for command. |
498 If command is a basename then PATH is searched for command. |
499 PATH isn't searched if command is an absolute or relative path. |
499 PATH isn't searched if command is an absolute or relative path. |
500 An extension from PATHEXT is found and added if not present. |
500 An extension from PATHEXT is found and added if not present. |
501 If command isn't found None is returned.''' |
501 If command isn't found None is returned.''' |
502 pathext = encoding.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD') |
502 pathext = encoding.environ.get(b'PATHEXT', b'.COM;.EXE;.BAT;.CMD') |
503 pathexts = [ext for ext in pathext.lower().split(pycompat.ospathsep)] |
503 pathexts = [ext for ext in pathext.lower().split(pycompat.ospathsep)] |
504 if os.path.splitext(command)[1].lower() in pathexts: |
504 if os.path.splitext(command)[1].lower() in pathexts: |
505 pathexts = [''] |
505 pathexts = [b''] |
506 |
506 |
507 def findexisting(pathcommand): |
507 def findexisting(pathcommand): |
508 'Will append extension (if needed) and return existing file' |
508 b'Will append extension (if needed) and return existing file' |
509 for ext in pathexts: |
509 for ext in pathexts: |
510 executable = pathcommand + ext |
510 executable = pathcommand + ext |
511 if os.path.exists(executable): |
511 if os.path.exists(executable): |
512 return executable |
512 return executable |
513 return None |
513 return None |
514 |
514 |
515 if pycompat.ossep in command: |
515 if pycompat.ossep in command: |
516 return findexisting(command) |
516 return findexisting(command) |
517 |
517 |
518 for path in encoding.environ.get('PATH', '').split(pycompat.ospathsep): |
518 for path in encoding.environ.get(b'PATH', b'').split(pycompat.ospathsep): |
519 executable = findexisting(os.path.join(path, command)) |
519 executable = findexisting(os.path.join(path, command)) |
520 if executable is not None: |
520 if executable is not None: |
521 return executable |
521 return executable |
522 return findexisting(os.path.expanduser(os.path.expandvars(command))) |
522 return findexisting(os.path.expanduser(os.path.expandvars(command))) |
523 |
523 |