msysutils.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. from io import open
  2. from os import environ
  3. from os.path import isfile
  4. from subprocess import PIPE, Popen
  5. import sys
  6. def _determineMounts():
  7. # The MSYS shell provides a Unix-like file system by translating paths on
  8. # the command line to Windows paths. Usually this is transparent, but not
  9. # for us since we call GCC without going through the shell.
  10. # Figure out the root directory of MSYS.
  11. proc = Popen(
  12. [ msysShell(), '-c', '"%s" -c \'import sys ; print sys.argv[1]\' /'
  13. % sys.executable.replace('\\', '\\\\') ],
  14. stdin = None,
  15. stdout = PIPE,
  16. stderr = PIPE,
  17. )
  18. stdoutdata, stderrdata = proc.communicate()
  19. if stderrdata or proc.returncode:
  20. if stderrdata:
  21. print('Error determining MSYS root:', stderrdata, file=sys.stderr)
  22. if proc.returncode:
  23. print('Exit code %d' % proc.returncode, file=sys.stderr)
  24. raise OSError('Error determining MSYS root')
  25. msysRoot = stdoutdata.strip()
  26. # Figure out all mount points of MSYS.
  27. mounts = {}
  28. fstab = msysRoot + '/etc/fstab'
  29. if isfile(fstab):
  30. try:
  31. with open(fstab, 'r', encoding='utf-8') as inp:
  32. for line in inp:
  33. line = line.strip()
  34. if line and not line.startswith('#'):
  35. nativePath, mountPoint = (
  36. path.rstrip('/') + '/' for path in line.split()[:2]
  37. )
  38. if nativePath != 'none':
  39. mounts[mountPoint] = nativePath
  40. except OSError as ex:
  41. print('Failed to read MSYS fstab:', ex, file=sys.stderr)
  42. except ValueError as ex:
  43. print('Failed to parse MSYS fstab:', ex, file=sys.stderr)
  44. mounts['/'] = msysRoot + '/'
  45. return mounts
  46. def msysPathToNative(path):
  47. if path.startswith('/'):
  48. if len(path) == 2 or (len(path) > 2 and path[2] == '/'):
  49. # Support drive letters as top-level dirs.
  50. return '%s:/%s' % (path[1], path[3 : ])
  51. longestMatch = ''
  52. for mountPoint in msysMounts.keys():
  53. if path.startswith(mountPoint):
  54. if len(mountPoint) > len(longestMatch):
  55. longestMatch = mountPoint
  56. return msysMounts[longestMatch] + path[len(longestMatch) : ]
  57. else:
  58. return path
  59. def msysActive():
  60. return environ.get('OSTYPE') == 'msys' or 'MSYSCON' in environ
  61. def msysShell():
  62. return environ.get('SHELL') or 'sh.exe'
  63. if msysActive():
  64. msysMounts = _determineMounts()
  65. else:
  66. msysMounts = None
  67. if __name__ == '__main__':
  68. print('MSYS mounts:', msysMounts)