159 # with exec bit on. |
159 # with exec bit on. |
160 |
160 |
161 try: |
161 try: |
162 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH |
162 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH |
163 cachedir = os.path.join(path, '.hg', 'cache') |
163 cachedir = os.path.join(path, '.hg', 'cache') |
164 if not os.path.isdir(cachedir): |
164 if os.path.isdir(cachedir): |
165 cachedir = path |
165 checkisexec = os.path.join(cachedir, 'checkisexec') |
166 fh, fn = tempfile.mkstemp(dir=cachedir, prefix='hg-checkexec-') |
166 checknoexec = os.path.join(cachedir, 'checknoexec') |
|
167 |
|
168 try: |
|
169 m = os.stat(checkisexec).st_mode |
|
170 except OSError as e: |
|
171 if e.errno != errno.ENOENT: |
|
172 raise |
|
173 # checkisexec does not exist - fall through ... |
|
174 else: |
|
175 # checkisexec exists, check if it actually is exec |
|
176 if m & EXECFLAGS != 0: |
|
177 # ensure checkisexec exists, check it isn't exec |
|
178 try: |
|
179 m = os.stat(checknoexec).st_mode |
|
180 except OSError as e: |
|
181 if e.errno != errno.ENOENT: |
|
182 raise |
|
183 file(checknoexec, 'w').close() # might fail |
|
184 m = os.stat(checknoexec).st_mode |
|
185 if m & EXECFLAGS == 0: |
|
186 # check-exec is exec and check-no-exec is not exec |
|
187 return True |
|
188 # checknoexec exists but is exec - delete it |
|
189 os.unlink(checknoexec) |
|
190 # checkisexec exists but is not exec - delete it |
|
191 os.unlink(checkisexec) |
|
192 |
|
193 # check using one file, leave it as checkisexec |
|
194 checkdir = cachedir |
|
195 else: |
|
196 # check directly in path and don't leave checkisexec behind |
|
197 checkdir = path |
|
198 checkisexec = None |
|
199 fh, fn = tempfile.mkstemp(dir=checkdir, prefix='hg-checkexec-') |
167 try: |
200 try: |
168 os.close(fh) |
201 os.close(fh) |
169 m = os.stat(fn).st_mode |
202 m = os.stat(fn).st_mode |
170 if m & EXECFLAGS: |
203 if m & EXECFLAGS == 0: |
171 return False |
204 os.chmod(fn, m & 0o777 | EXECFLAGS) |
172 os.chmod(fn, m & 0o777 | EXECFLAGS) |
205 if os.stat(fn).st_mode & EXECFLAGS != 0: |
173 return os.stat(fn).st_mode & EXECFLAGS |
206 if checkisexec is not None: |
|
207 os.rename(fn, checkisexec) |
|
208 fn = None |
|
209 return True |
174 finally: |
210 finally: |
175 os.unlink(fn) |
211 if fn is not None: |
|
212 os.unlink(fn) |
176 except (IOError, OSError): |
213 except (IOError, OSError): |
177 # we don't care, the user probably won't be able to commit anyway |
214 # we don't care, the user probably won't be able to commit anyway |
178 return False |
215 return False |
179 |
216 |
180 def checklink(path): |
217 def checklink(path): |