Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: client/utils/fs.py

Issue 2668503008: implement unlink on Windows (Closed)
Patch Set: pylint... Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2015 The LUCI Authors. All rights reserved. 1 # Copyright 2015 The LUCI Authors. All rights reserved.
2 # Use of this source code is governed under the Apache License, Version 2.0 2 # Use of this source code is governed under the Apache License, Version 2.0
3 # that can be found in the LICENSE file. 3 # that can be found in the LICENSE file.
4 4
5 """Wraps os, os.path and shutil functions to work around MAX_PATH on Windows.""" 5 """Wraps os, os.path and shutil functions to work around MAX_PATH on Windows."""
6 6
7 import __builtin__ 7 import __builtin__
8 import inspect 8 import inspect
9 import os 9 import os
10 import shutil 10 import shutil
11 import sys 11 import sys
12 12
13 13
14 if sys.platform == 'win32': 14 if sys.platform == 'win32':
15 15
16 16
17 import ctypes 17 import ctypes
18 GetFileAttributesW = ctypes.windll.kernel32.GetFileAttributesW
19 GetFileAttributesW.argtypes = (ctypes.c_wchar_p,)
20 GetFileAttributesW.restype = ctypes.c_uint
21 CreateSymbolicLinkW = ctypes.windll.kernel32.CreateSymbolicLinkW 18 CreateSymbolicLinkW = ctypes.windll.kernel32.CreateSymbolicLinkW
22 CreateSymbolicLinkW.argtypes = ( 19 CreateSymbolicLinkW.argtypes = (
23 ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32) 20 ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32)
24 CreateSymbolicLinkW.restype = ctypes.c_ubyte 21 CreateSymbolicLinkW.restype = ctypes.c_ubyte
22 DeleteFile = ctypes.windll.kernel32.DeleteFileW
23 DeleteFile.argtypes = (ctypes.c_wchar_p,)
24 DeleteFile.restype = ctypes.c_bool
25 GetFileAttributesW = ctypes.windll.kernel32.GetFileAttributesW
26 GetFileAttributesW.argtypes = (ctypes.c_wchar_p,)
27 GetFileAttributesW.restype = ctypes.c_uint
28 RemoveDirectory = ctypes.windll.kernel32.RemoveDirectoryW
29 RemoveDirectory.argtypes = (ctypes.c_wchar_p,)
30 RemoveDirectory.restype = ctypes.c_bool
25 31
26 32
27 def extend(path): 33 def extend(path):
28 """Adds '\\\\?\\' when given an absolute path so the MAX_PATH (260) limit is 34 """Adds '\\\\?\\' when given an absolute path so the MAX_PATH (260) limit is
29 not enforced. 35 not enforced.
30 """ 36 """
31 assert os.path.isabs(path), path 37 assert os.path.isabs(path), path
32 assert isinstance(path, unicode), path 38 assert isinstance(path, unicode), path
33 prefix = u'\\\\?\\' 39 prefix = u'\\\\?\\'
34 return path if path.startswith(prefix) else prefix + path 40 return path if path.startswith(prefix) else prefix + path
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 Privilege constants: 74 Privilege constants:
69 https://msdn.microsoft.com/library/windows/desktop/bb530716.aspx 75 https://msdn.microsoft.com/library/windows/desktop/bb530716.aspx
70 """ 76 """
71 # TODO(maruel): This forces always creating absolute path symlinks. 77 # TODO(maruel): This forces always creating absolute path symlinks.
72 source = extend(source) 78 source = extend(source)
73 flags = 1 if os.path.isdir(source) else 0 79 flags = 1 if os.path.isdir(source) else 0
74 if not CreateSymbolicLinkW(extend(link_name), source, flags): 80 if not CreateSymbolicLinkW(extend(link_name), source, flags):
75 raise WindowsError() # pylint: disable=undefined-variable 81 raise WindowsError() # pylint: disable=undefined-variable
76 82
77 83
84 def unlink(path):
85 """Removes a symlink on Windows 7 and later.
86
87 Does not delete the link source.
88
89 If path is not a link, but a non-empty directory, will fail with a
90 WindowsError.
91
92 Useful material:
93 CreateSymbolicLinkW:
94 https://msdn.microsoft.com/library/windows/desktop/aa363866.aspx
95 DeleteFileW:
96 https://msdn.microsoft.com/en-us/library/windows/desktop/aa363915(v=vs.85) .aspx
97 RemoveDirectoryW:
98 https://msdn.microsoft.com/en-us/library/windows/desktop/aa365488(v=vs.85) .aspx
99 """
100 path = extend(path)
101 if os.path.isdir(path):
102 if not RemoveDirectory(path):
103 # pylint: disable=undefined-variable
104 raise WindowsError('could not remove directory "%s"' % path)
105 else:
106 if not DeleteFile(path):
107 # pylint: disable=undefined-variable
108 raise WindowsError('could not delete file "%s"' % path)
109
110
78 def walk(top, *args, **kwargs): 111 def walk(top, *args, **kwargs):
79 return os.walk(extend(top), *args, **kwargs) 112 return os.walk(extend(top), *args, **kwargs)
80 113
81 114
82 else: 115 else:
83 116
84 117
85 def extend(path): 118 def extend(path):
86 """Convert the path back to utf-8. 119 """Convert the path back to utf-8.
87 120
(...skipping 12 matching lines...) Expand all
100 return path.decode('utf-8') 133 return path.decode('utf-8')
101 134
102 135
103 def islink(path): 136 def islink(path):
104 return os.path.islink(extend(path)) 137 return os.path.islink(extend(path))
105 138
106 139
107 def symlink(source, link_name): 140 def symlink(source, link_name):
108 return os.symlink(source, extend(link_name)) 141 return os.symlink(source, extend(link_name))
109 142
143 def unlink(path):
144 return os.unlink(extend(path))
110 145
111 def walk(top, *args, **kwargs): 146 def walk(top, *args, **kwargs):
112 for root, dirs, files in os.walk(extend(top), *args, **kwargs): 147 for root, dirs, files in os.walk(extend(top), *args, **kwargs):
113 yield trim(root), dirs, files 148 yield trim(root), dirs, files
114 149
115 150
116 ## builtin 151 ## builtin
117 152
118 153
119 def open(path, *args, **kwargs): # pylint: disable=redefined-builtin 154 def open(path, *args, **kwargs): # pylint: disable=redefined-builtin
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 for _fn in _os_fns: 205 for _fn in _os_fns:
171 if hasattr(os, _fn): 206 if hasattr(os, _fn):
172 sys.modules[__name__].__dict__.setdefault( 207 sys.modules[__name__].__dict__.setdefault(
173 _fn, _get_lambda(getattr(os, _fn))) 208 _fn, _get_lambda(getattr(os, _fn)))
174 209
175 210
176 for _fn in _os_path_fns: 211 for _fn in _os_path_fns:
177 if hasattr(os.path, _fn): 212 if hasattr(os.path, _fn):
178 sys.modules[__name__].__dict__.setdefault( 213 sys.modules[__name__].__dict__.setdefault(
179 _fn, _get_lambda(getattr(os.path, _fn))) 214 _fn, _get_lambda(getattr(os.path, _fn)))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698