mercurial/util_win32.py
changeset 2176 9b42304d9896
parent 2117 760339ccc799
child 2243 caf2c6ef5b0e
equal deleted inserted replaced
2129:e5f5c21f4169 2176:9b42304d9896
    14 import win32api
    14 import win32api
    15 
    15 
    16 from demandload import *
    16 from demandload import *
    17 from i18n import gettext as _
    17 from i18n import gettext as _
    18 demandload(globals(), 'errno os pywintypes win32con win32file win32process')
    18 demandload(globals(), 'errno os pywintypes win32con win32file win32process')
    19 demandload(globals(), 'winerror')
    19 demandload(globals(), 'cStringIO winerror')
    20 
    20 
    21 class WinError(OSError):
    21 class WinError:
    22     winerror_map = {
    22     winerror_map = {
    23         winerror.ERROR_ACCESS_DENIED: errno.EACCES,
    23         winerror.ERROR_ACCESS_DENIED: errno.EACCES,
    24         winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
    24         winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
    25         winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES,
    25         winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES,
    26         winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY,
    26         winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY,
   103         winerror.ERROR_OPEN_FILES: errno.EBUSY,
   103         winerror.ERROR_OPEN_FILES: errno.EBUSY,
   104         winerror.ERROR_OPERATION_ABORTED: errno.EINTR,
   104         winerror.ERROR_OPERATION_ABORTED: errno.EINTR,
   105         winerror.ERROR_OUTOFMEMORY: errno.ENOMEM,
   105         winerror.ERROR_OUTOFMEMORY: errno.ENOMEM,
   106         winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES,
   106         winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES,
   107         winerror.ERROR_PATH_BUSY: errno.EBUSY,
   107         winerror.ERROR_PATH_BUSY: errno.EBUSY,
   108         winerror.ERROR_PATH_NOT_FOUND: errno.ENOTDIR,
   108         winerror.ERROR_PATH_NOT_FOUND: errno.ENOENT,
   109         winerror.ERROR_PIPE_BUSY: errno.EBUSY,
   109         winerror.ERROR_PIPE_BUSY: errno.EBUSY,
   110         winerror.ERROR_PIPE_CONNECTED: errno.EPIPE,
   110         winerror.ERROR_PIPE_CONNECTED: errno.EPIPE,
   111         winerror.ERROR_PIPE_LISTENING: errno.EPIPE,
   111         winerror.ERROR_PIPE_LISTENING: errno.EPIPE,
   112         winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE,
   112         winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE,
   113         winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES,
   113         winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES,
   127         winerror.ERROR_WRITE_PROTECT: errno.EROFS,
   127         winerror.ERROR_WRITE_PROTECT: errno.EROFS,
   128         }
   128         }
   129 
   129 
   130     def __init__(self, err):
   130     def __init__(self, err):
   131         self.win_errno, self.win_function, self.win_strerror = err
   131         self.win_errno, self.win_function, self.win_strerror = err
       
   132         if self.win_strerror.endswith('.'):
       
   133             self.win_strerror = self.win_strerror[:-1]
       
   134 
       
   135 class WinIOError(WinError, IOError):
       
   136     def __init__(self, err, filename=None):
       
   137         WinError.__init__(self, err)
       
   138         IOError.__init__(self, self.winerror_map.get(self.win_errno, 0),
       
   139                          self.win_strerror)
       
   140         self.filename = filename
       
   141 
       
   142 class WinOSError(WinError, OSError):
       
   143     def __init__(self, err):
       
   144         WinError.__init__(self, err)
   132         OSError.__init__(self, self.winerror_map.get(self.win_errno, 0),
   145         OSError.__init__(self, self.winerror_map.get(self.win_errno, 0),
   133                          self.win_strerror)
   146                          self.win_strerror)
   134 
   147 
   135 def os_link(src, dst):
   148 def os_link(src, dst):
   136     # NB will only succeed on NTFS
   149     # NB will only succeed on NTFS
   137     try:
   150     try:
   138         win32file.CreateHardLink(dst, src)
   151         win32file.CreateHardLink(dst, src)
   139     except pywintypes.error, details:
   152     except pywintypes.error, details:
   140         raise WinError(details)
   153         raise WinOSError(details)
   141 
   154 
   142 def nlinks(pathname):
   155 def nlinks(pathname):
   143     """Return number of hardlinks for the given file."""
   156     """Return number of hardlinks for the given file."""
   144     try:
   157     try:
   145         fh = win32file.CreateFile(pathname,
   158         fh = win32file.CreateFile(pathname,
   167 def system_rcpath_win32():
   180 def system_rcpath_win32():
   168     '''return default os-specific hgrc search path'''
   181     '''return default os-specific hgrc search path'''
   169     proc = win32api.GetCurrentProcess()
   182     proc = win32api.GetCurrentProcess()
   170     filename = win32process.GetModuleFileNameEx(proc, 0)
   183     filename = win32process.GetModuleFileNameEx(proc, 0)
   171     return [os.path.join(os.path.dirname(filename), 'mercurial.ini')]
   184     return [os.path.join(os.path.dirname(filename), 'mercurial.ini')]
       
   185 
       
   186 class posixfile(object):
       
   187     '''file object with posix-like semantics.  on windows, normal
       
   188     files can not be deleted or renamed if they are open. must open
       
   189     with win32file.FILE_SHARE_DELETE. this flag does not exist on
       
   190     windows <= nt.'''
       
   191 
       
   192     # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
       
   193     # but does not work at all. wrap win32 file api instead.
       
   194 
       
   195     def __init__(self, name, mode='rb'):
       
   196         access = 0
       
   197         if 'r' in mode or '+' in mode:
       
   198             access |= win32file.GENERIC_READ
       
   199         if 'w' in mode or 'a' in mode:
       
   200             access |= win32file.GENERIC_WRITE
       
   201         if 'r' in mode:
       
   202             creation = win32file.OPEN_EXISTING
       
   203         elif 'a' in mode:
       
   204             creation = win32file.OPEN_ALWAYS
       
   205         else:
       
   206             creation = win32file.CREATE_ALWAYS
       
   207         try:
       
   208             self.handle = win32file.CreateFile(name,
       
   209                                                access,
       
   210                                                win32file.FILE_SHARE_READ |
       
   211                                                win32file.FILE_SHARE_WRITE |
       
   212                                                win32file.FILE_SHARE_DELETE,
       
   213                                                None,
       
   214                                                creation,
       
   215                                                win32file.FILE_ATTRIBUTE_NORMAL,
       
   216                                                0)
       
   217         except pywintypes.error, err:
       
   218             raise WinIOError(err, name)
       
   219         self.closed = False
       
   220         self.name = name
       
   221         self.mode = mode
       
   222 
       
   223     def read(self, count=-1):
       
   224         try:
       
   225             cs = cStringIO.StringIO()
       
   226             while count:
       
   227                 wincount = int(count)
       
   228                 if wincount == -1:
       
   229                     wincount = 1048576
       
   230                 val, data = win32file.ReadFile(self.handle, wincount)
       
   231                 if not data: break
       
   232                 cs.write(data)
       
   233                 if count != -1:
       
   234                     count -= len(data)
       
   235             return cs.getvalue()
       
   236         except pywintypes.error, err:
       
   237             raise WinIOError(err)
       
   238 
       
   239     def write(self, data):
       
   240         try:
       
   241             if 'a' in self.mode:
       
   242                 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
       
   243             nwrit = 0
       
   244             while nwrit < len(data):
       
   245                 val, nwrit = win32file.WriteFile(self.handle, data)
       
   246                 data = data[nwrit:]
       
   247         except pywintypes.error, err:
       
   248             raise WinIOError(err)
       
   249 
       
   250     def seek(self, pos, whence=0):
       
   251         try:
       
   252             win32file.SetFilePointer(self.handle, int(pos), whence)
       
   253         except pywintypes.error, err:
       
   254             raise WinIOError(err)
       
   255 
       
   256     def tell(self):
       
   257         try:
       
   258             return win32file.SetFilePointer(self.handle, 0,
       
   259                                             win32file.FILE_CURRENT)
       
   260         except pywintypes.error, err:
       
   261             raise WinIOError(err)
       
   262 
       
   263     def close(self):
       
   264         if not self.closed:
       
   265             self.handle = None
       
   266             self.closed = True
       
   267 
       
   268     def flush(self):
       
   269         try:
       
   270             win32file.FlushFileBuffers(self.handle)
       
   271         except pywintypes.error, err:
       
   272             raise WinIOError(err)
       
   273 
       
   274     def truncate(self, pos=0):
       
   275         try:
       
   276             win32file.SetFilePointer(self.handle, int(pos),
       
   277                                      win32file.FILE_BEGIN)
       
   278             win32file.SetEndOfFile(self.handle)
       
   279         except pywintypes.error, err:
       
   280             raise WinIOError(err)