1 |
Author: zmedico |
2 |
Date: 2010-02-25 21:52:38 +0000 (Thu, 25 Feb 2010) |
3 |
New Revision: 15464 |
4 |
|
5 |
Added: |
6 |
main/trunk/pym/portage/util/movefile.py |
7 |
Modified: |
8 |
main/trunk/pym/portage/__init__.py |
9 |
main/trunk/pym/portage/dbapi/vartree.py |
10 |
Log: |
11 |
Move portage.movefile to portage.util.movefile. |
12 |
|
13 |
|
14 |
Modified: main/trunk/pym/portage/__init__.py |
15 |
=================================================================== |
16 |
--- main/trunk/pym/portage/__init__.py 2010-02-25 21:38:30 UTC (rev 15463) |
17 |
+++ main/trunk/pym/portage/__init__.py 2010-02-25 21:52:38 UTC (rev 15464) |
18 |
@@ -130,6 +130,7 @@ |
19 |
'portage.util.env_update:env_update', |
20 |
'portage.util.ExtractKernelVersion:ExtractKernelVersion', |
21 |
'portage.util.listdir:cacheddir,listdir', |
22 |
+ 'portage.util.movefile:movefile', |
23 |
'portage.versions', |
24 |
'portage.versions:best,catpkgsplit,catsplit,cpv_getkey,' + \ |
25 |
'cpv_getkey@getCPFromCPV,endversion_keys,' + \ |
26 |
@@ -638,223 +639,6 @@ |
27 |
raise portage.exception.PortageException( |
28 |
"mv '%s' '%s'" % (src, dest)) |
29 |
|
30 |
-def movefile(src, dest, newmtime=None, sstat=None, mysettings=None, |
31 |
- hardlink_candidates=None, encoding=_encodings['fs']): |
32 |
- """moves a file from src to dest, preserving all permissions and attributes; mtime will |
33 |
- be preserved even when moving across filesystems. Returns true on success and false on |
34 |
- failure. Move is atomic.""" |
35 |
- #print "movefile("+str(src)+","+str(dest)+","+str(newmtime)+","+str(sstat)+")" |
36 |
- |
37 |
- if mysettings is None: |
38 |
- global settings |
39 |
- mysettings = settings |
40 |
- |
41 |
- selinux_enabled = mysettings.selinux_enabled() |
42 |
- if selinux_enabled: |
43 |
- selinux = _unicode_module_wrapper(_selinux, encoding=encoding) |
44 |
- |
45 |
- lchown = _unicode_func_wrapper(data.lchown, encoding=encoding) |
46 |
- os = _unicode_module_wrapper(_os, |
47 |
- encoding=encoding, overrides=_os_overrides) |
48 |
- shutil = _unicode_module_wrapper(_shutil, encoding=encoding) |
49 |
- |
50 |
- try: |
51 |
- if not sstat: |
52 |
- sstat=os.lstat(src) |
53 |
- |
54 |
- except SystemExit as e: |
55 |
- raise |
56 |
- except Exception as e: |
57 |
- print(_("!!! Stating source file failed... movefile()")) |
58 |
- print("!!!",e) |
59 |
- return None |
60 |
- |
61 |
- destexists=1 |
62 |
- try: |
63 |
- dstat=os.lstat(dest) |
64 |
- except (OSError, IOError): |
65 |
- dstat=os.lstat(os.path.dirname(dest)) |
66 |
- destexists=0 |
67 |
- |
68 |
- if bsd_chflags: |
69 |
- if destexists and dstat.st_flags != 0: |
70 |
- bsd_chflags.lchflags(dest, 0) |
71 |
- # Use normal stat/chflags for the parent since we want to |
72 |
- # follow any symlinks to the real parent directory. |
73 |
- pflags = os.stat(os.path.dirname(dest)).st_flags |
74 |
- if pflags != 0: |
75 |
- bsd_chflags.chflags(os.path.dirname(dest), 0) |
76 |
- |
77 |
- if destexists: |
78 |
- if stat.S_ISLNK(dstat[stat.ST_MODE]): |
79 |
- try: |
80 |
- os.unlink(dest) |
81 |
- destexists=0 |
82 |
- except SystemExit as e: |
83 |
- raise |
84 |
- except Exception as e: |
85 |
- pass |
86 |
- |
87 |
- if stat.S_ISLNK(sstat[stat.ST_MODE]): |
88 |
- try: |
89 |
- target=os.readlink(src) |
90 |
- if mysettings and mysettings["D"]: |
91 |
- if target.find(mysettings["D"])==0: |
92 |
- target=target[len(mysettings["D"]):] |
93 |
- if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]): |
94 |
- os.unlink(dest) |
95 |
- if selinux_enabled: |
96 |
- selinux.symlink(target, dest, src) |
97 |
- else: |
98 |
- os.symlink(target,dest) |
99 |
- lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) |
100 |
- # utime() only works on the target of a symlink, so it's not |
101 |
- # possible to perserve mtime on symlinks. |
102 |
- return os.lstat(dest)[stat.ST_MTIME] |
103 |
- except SystemExit as e: |
104 |
- raise |
105 |
- except Exception as e: |
106 |
- print(_("!!! failed to properly create symlink:")) |
107 |
- print("!!!",dest,"->",target) |
108 |
- print("!!!",e) |
109 |
- return None |
110 |
- |
111 |
- hardlinked = False |
112 |
- # Since identical files might be merged to multiple filesystems, |
113 |
- # so os.link() calls might fail for some paths, so try them all. |
114 |
- # For atomic replacement, first create the link as a temp file |
115 |
- # and them use os.rename() to replace the destination. |
116 |
- if hardlink_candidates: |
117 |
- head, tail = os.path.split(dest) |
118 |
- hardlink_tmp = os.path.join(head, ".%s._portage_merge_.%s" % \ |
119 |
- (tail, os.getpid())) |
120 |
- try: |
121 |
- os.unlink(hardlink_tmp) |
122 |
- except OSError as e: |
123 |
- if e.errno != errno.ENOENT: |
124 |
- writemsg(_("!!! Failed to remove hardlink temp file: %s\n") % \ |
125 |
- (hardlink_tmp,), noiselevel=-1) |
126 |
- writemsg("!!! %s\n" % (e,), noiselevel=-1) |
127 |
- return None |
128 |
- del e |
129 |
- for hardlink_src in hardlink_candidates: |
130 |
- try: |
131 |
- os.link(hardlink_src, hardlink_tmp) |
132 |
- except OSError: |
133 |
- continue |
134 |
- else: |
135 |
- try: |
136 |
- os.rename(hardlink_tmp, dest) |
137 |
- except OSError as e: |
138 |
- writemsg(_("!!! Failed to rename %s to %s\n") % \ |
139 |
- (hardlink_tmp, dest), noiselevel=-1) |
140 |
- writemsg("!!! %s\n" % (e,), noiselevel=-1) |
141 |
- return None |
142 |
- hardlinked = True |
143 |
- break |
144 |
- |
145 |
- renamefailed=1 |
146 |
- if hardlinked: |
147 |
- renamefailed = False |
148 |
- if not hardlinked and (selinux_enabled or sstat.st_dev == dstat.st_dev): |
149 |
- try: |
150 |
- if selinux_enabled: |
151 |
- ret = selinux.rename(src, dest) |
152 |
- else: |
153 |
- ret=os.rename(src,dest) |
154 |
- renamefailed=0 |
155 |
- except OSError as e: |
156 |
- if e.errno != errno.EXDEV: |
157 |
- # Some random error. |
158 |
- print(_("!!! Failed to move %(src)s to %(dest)s") % {"src": src, "dest": dest}) |
159 |
- print("!!!",e) |
160 |
- return None |
161 |
- # Invalid cross-device-link 'bind' mounted or actually Cross-Device |
162 |
- if renamefailed: |
163 |
- didcopy=0 |
164 |
- if stat.S_ISREG(sstat[stat.ST_MODE]): |
165 |
- try: # For safety copy then move it over. |
166 |
- if selinux_enabled: |
167 |
- selinux.copyfile(src, dest + "#new") |
168 |
- selinux.rename(dest + "#new", dest) |
169 |
- else: |
170 |
- shutil.copyfile(src,dest+"#new") |
171 |
- os.rename(dest+"#new",dest) |
172 |
- didcopy=1 |
173 |
- except SystemExit as e: |
174 |
- raise |
175 |
- except Exception as e: |
176 |
- print(_('!!! copy %(src)s -> %(dest)s failed.') % {"src": src, "dest": dest}) |
177 |
- print("!!!",e) |
178 |
- return None |
179 |
- else: |
180 |
- #we don't yet handle special, so we need to fall back to /bin/mv |
181 |
- a = process.spawn([MOVE_BINARY, '-f', src, dest], env=os.environ) |
182 |
- if a != os.EX_OK: |
183 |
- writemsg(_("!!! Failed to move special file:\n"), noiselevel=-1) |
184 |
- writemsg(_("!!! '%(src)s' to '%(dest)s'\n") % \ |
185 |
- {"src": _unicode_decode(src, encoding=encoding), |
186 |
- "dest": _unicode_decode(dest, encoding=encoding)}, noiselevel=-1) |
187 |
- writemsg("!!! %s\n" % a, noiselevel=-1) |
188 |
- return None # failure |
189 |
- try: |
190 |
- if didcopy: |
191 |
- if stat.S_ISLNK(sstat[stat.ST_MODE]): |
192 |
- lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) |
193 |
- else: |
194 |
- os.chown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) |
195 |
- os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown |
196 |
- os.unlink(src) |
197 |
- except SystemExit as e: |
198 |
- raise |
199 |
- except Exception as e: |
200 |
- print(_("!!! Failed to chown/chmod/unlink in movefile()")) |
201 |
- print("!!!",dest) |
202 |
- print("!!!",e) |
203 |
- return None |
204 |
- |
205 |
- # Always use stat_obj[stat.ST_MTIME] for the integral timestamp which |
206 |
- # is returned, since the stat_obj.st_mtime float attribute rounds *up* |
207 |
- # if the nanosecond part of the timestamp is 999999881 ns or greater. |
208 |
- try: |
209 |
- if hardlinked: |
210 |
- newmtime = os.stat(dest)[stat.ST_MTIME] |
211 |
- else: |
212 |
- # Note: It is not possible to preserve nanosecond precision |
213 |
- # (supported in POSIX.1-2008 via utimensat) with the IEEE 754 |
214 |
- # double precision float which only has a 53 bit significand. |
215 |
- if newmtime is not None: |
216 |
- os.utime(dest, (newmtime, newmtime)) |
217 |
- else: |
218 |
- newmtime = sstat[stat.ST_MTIME] |
219 |
- if renamefailed: |
220 |
- # If rename succeeded then timestamps are automatically |
221 |
- # preserved with complete precision because the source |
222 |
- # and destination inode are the same. Otherwise, round |
223 |
- # down to the nearest whole second since python's float |
224 |
- # st_mtime cannot be used to preserve the st_mtim.tv_nsec |
225 |
- # field with complete precision. Note that we have to use |
226 |
- # stat_obj[stat.ST_MTIME] here because the float |
227 |
- # stat_obj.st_mtime rounds *up* sometimes. |
228 |
- os.utime(dest, (newmtime, newmtime)) |
229 |
- except OSError: |
230 |
- # The utime can fail here with EPERM even though the move succeeded. |
231 |
- # Instead of failing, use stat to return the mtime if possible. |
232 |
- try: |
233 |
- newmtime = os.stat(dest)[stat.ST_MTIME] |
234 |
- except OSError as e: |
235 |
- writemsg(_("!!! Failed to stat in movefile()\n"), noiselevel=-1) |
236 |
- writemsg("!!! %s\n" % dest, noiselevel=-1) |
237 |
- writemsg("!!! %s\n" % str(e), noiselevel=-1) |
238 |
- return None |
239 |
- |
240 |
- if bsd_chflags: |
241 |
- # Restore the flags we saved before moving |
242 |
- if pflags: |
243 |
- bsd_chflags.chflags(os.path.dirname(dest), pflags) |
244 |
- |
245 |
- return newmtime |
246 |
- |
247 |
def merge(mycat, mypkg, pkgloc, infloc, myroot, mysettings, myebuild=None, |
248 |
mytree=None, mydbapi=None, vartree=None, prev_mtimes=None, blockers=None, |
249 |
scheduler=None): |
250 |
|
251 |
Modified: main/trunk/pym/portage/dbapi/vartree.py |
252 |
=================================================================== |
253 |
--- main/trunk/pym/portage/dbapi/vartree.py 2010-02-25 21:38:30 UTC (rev 15463) |
254 |
+++ main/trunk/pym/portage/dbapi/vartree.py 2010-02-25 21:52:38 UTC (rev 15464) |
255 |
@@ -39,8 +39,9 @@ |
256 |
InvalidData, InvalidPackageName, \ |
257 |
FileNotFound, PermissionDenied, UnsupportedAPIException |
258 |
from portage.localization import _ |
259 |
+from portage.util.movefile import movefile |
260 |
|
261 |
-from portage import abssymlink, movefile, _movefile, bsd_chflags |
262 |
+from portage import abssymlink, _movefile, bsd_chflags |
263 |
|
264 |
# This is a special version of the os module, wrapped for unicode support. |
265 |
from portage import os |
266 |
|
267 |
Added: main/trunk/pym/portage/util/movefile.py |
268 |
=================================================================== |
269 |
--- main/trunk/pym/portage/util/movefile.py (rev 0) |
270 |
+++ main/trunk/pym/portage/util/movefile.py 2010-02-25 21:52:38 UTC (rev 15464) |
271 |
@@ -0,0 +1,234 @@ |
272 |
+# Copyright 2010 Gentoo Foundation |
273 |
+# Distributed under the terms of the GNU General Public License v2 |
274 |
+# $Id$ |
275 |
+ |
276 |
+__all__ = ['movefile'] |
277 |
+ |
278 |
+import errno |
279 |
+import os as _os |
280 |
+import shutil as _shutil |
281 |
+import stat |
282 |
+ |
283 |
+import portage |
284 |
+from portage import bsd_chflags, _encodings, _os_overrides, _selinux, \ |
285 |
+ _unicode_decode, _unicode_func_wrapper, _unicode_module_wrapper |
286 |
+from portage.const import MOVE_BINARY |
287 |
+from portage.localization import _ |
288 |
+from portage.process import spawn |
289 |
+from portage.util import writemsg |
290 |
+ |
291 |
+def movefile(src, dest, newmtime=None, sstat=None, mysettings=None, |
292 |
+ hardlink_candidates=None, encoding=_encodings['fs']): |
293 |
+ """moves a file from src to dest, preserving all permissions and attributes; mtime will |
294 |
+ be preserved even when moving across filesystems. Returns true on success and false on |
295 |
+ failure. Move is atomic.""" |
296 |
+ #print "movefile("+str(src)+","+str(dest)+","+str(newmtime)+","+str(sstat)+")" |
297 |
+ |
298 |
+ if mysettings is None: |
299 |
+ mysettings = portage.settings |
300 |
+ |
301 |
+ selinux_enabled = mysettings.selinux_enabled() |
302 |
+ if selinux_enabled: |
303 |
+ selinux = _unicode_module_wrapper(_selinux, encoding=encoding) |
304 |
+ |
305 |
+ lchown = _unicode_func_wrapper(portage.data.lchown, encoding=encoding) |
306 |
+ os = _unicode_module_wrapper(_os, |
307 |
+ encoding=encoding, overrides=_os_overrides) |
308 |
+ shutil = _unicode_module_wrapper(_shutil, encoding=encoding) |
309 |
+ |
310 |
+ try: |
311 |
+ if not sstat: |
312 |
+ sstat=os.lstat(src) |
313 |
+ |
314 |
+ except SystemExit as e: |
315 |
+ raise |
316 |
+ except Exception as e: |
317 |
+ print(_("!!! Stating source file failed... movefile()")) |
318 |
+ print("!!!",e) |
319 |
+ return None |
320 |
+ |
321 |
+ destexists=1 |
322 |
+ try: |
323 |
+ dstat=os.lstat(dest) |
324 |
+ except (OSError, IOError): |
325 |
+ dstat=os.lstat(os.path.dirname(dest)) |
326 |
+ destexists=0 |
327 |
+ |
328 |
+ if bsd_chflags: |
329 |
+ if destexists and dstat.st_flags != 0: |
330 |
+ bsd_chflags.lchflags(dest, 0) |
331 |
+ # Use normal stat/chflags for the parent since we want to |
332 |
+ # follow any symlinks to the real parent directory. |
333 |
+ pflags = os.stat(os.path.dirname(dest)).st_flags |
334 |
+ if pflags != 0: |
335 |
+ bsd_chflags.chflags(os.path.dirname(dest), 0) |
336 |
+ |
337 |
+ if destexists: |
338 |
+ if stat.S_ISLNK(dstat[stat.ST_MODE]): |
339 |
+ try: |
340 |
+ os.unlink(dest) |
341 |
+ destexists=0 |
342 |
+ except SystemExit as e: |
343 |
+ raise |
344 |
+ except Exception as e: |
345 |
+ pass |
346 |
+ |
347 |
+ if stat.S_ISLNK(sstat[stat.ST_MODE]): |
348 |
+ try: |
349 |
+ target=os.readlink(src) |
350 |
+ if mysettings and mysettings["D"]: |
351 |
+ if target.find(mysettings["D"])==0: |
352 |
+ target=target[len(mysettings["D"]):] |
353 |
+ if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]): |
354 |
+ os.unlink(dest) |
355 |
+ if selinux_enabled: |
356 |
+ selinux.symlink(target, dest, src) |
357 |
+ else: |
358 |
+ os.symlink(target,dest) |
359 |
+ lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) |
360 |
+ # utime() only works on the target of a symlink, so it's not |
361 |
+ # possible to perserve mtime on symlinks. |
362 |
+ return os.lstat(dest)[stat.ST_MTIME] |
363 |
+ except SystemExit as e: |
364 |
+ raise |
365 |
+ except Exception as e: |
366 |
+ print(_("!!! failed to properly create symlink:")) |
367 |
+ print("!!!",dest,"->",target) |
368 |
+ print("!!!",e) |
369 |
+ return None |
370 |
+ |
371 |
+ hardlinked = False |
372 |
+ # Since identical files might be merged to multiple filesystems, |
373 |
+ # so os.link() calls might fail for some paths, so try them all. |
374 |
+ # For atomic replacement, first create the link as a temp file |
375 |
+ # and them use os.rename() to replace the destination. |
376 |
+ if hardlink_candidates: |
377 |
+ head, tail = os.path.split(dest) |
378 |
+ hardlink_tmp = os.path.join(head, ".%s._portage_merge_.%s" % \ |
379 |
+ (tail, os.getpid())) |
380 |
+ try: |
381 |
+ os.unlink(hardlink_tmp) |
382 |
+ except OSError as e: |
383 |
+ if e.errno != errno.ENOENT: |
384 |
+ writemsg(_("!!! Failed to remove hardlink temp file: %s\n") % \ |
385 |
+ (hardlink_tmp,), noiselevel=-1) |
386 |
+ writemsg("!!! %s\n" % (e,), noiselevel=-1) |
387 |
+ return None |
388 |
+ del e |
389 |
+ for hardlink_src in hardlink_candidates: |
390 |
+ try: |
391 |
+ os.link(hardlink_src, hardlink_tmp) |
392 |
+ except OSError: |
393 |
+ continue |
394 |
+ else: |
395 |
+ try: |
396 |
+ os.rename(hardlink_tmp, dest) |
397 |
+ except OSError as e: |
398 |
+ writemsg(_("!!! Failed to rename %s to %s\n") % \ |
399 |
+ (hardlink_tmp, dest), noiselevel=-1) |
400 |
+ writemsg("!!! %s\n" % (e,), noiselevel=-1) |
401 |
+ return None |
402 |
+ hardlinked = True |
403 |
+ break |
404 |
+ |
405 |
+ renamefailed=1 |
406 |
+ if hardlinked: |
407 |
+ renamefailed = False |
408 |
+ if not hardlinked and (selinux_enabled or sstat.st_dev == dstat.st_dev): |
409 |
+ try: |
410 |
+ if selinux_enabled: |
411 |
+ selinux.rename(src, dest) |
412 |
+ else: |
413 |
+ os.rename(src,dest) |
414 |
+ renamefailed=0 |
415 |
+ except OSError as e: |
416 |
+ if e.errno != errno.EXDEV: |
417 |
+ # Some random error. |
418 |
+ print(_("!!! Failed to move %(src)s to %(dest)s") % {"src": src, "dest": dest}) |
419 |
+ print("!!!",e) |
420 |
+ return None |
421 |
+ # Invalid cross-device-link 'bind' mounted or actually Cross-Device |
422 |
+ if renamefailed: |
423 |
+ didcopy=0 |
424 |
+ if stat.S_ISREG(sstat[stat.ST_MODE]): |
425 |
+ try: # For safety copy then move it over. |
426 |
+ if selinux_enabled: |
427 |
+ selinux.copyfile(src, dest + "#new") |
428 |
+ selinux.rename(dest + "#new", dest) |
429 |
+ else: |
430 |
+ shutil.copyfile(src,dest+"#new") |
431 |
+ os.rename(dest+"#new",dest) |
432 |
+ didcopy=1 |
433 |
+ except SystemExit as e: |
434 |
+ raise |
435 |
+ except Exception as e: |
436 |
+ print(_('!!! copy %(src)s -> %(dest)s failed.') % {"src": src, "dest": dest}) |
437 |
+ print("!!!",e) |
438 |
+ return None |
439 |
+ else: |
440 |
+ #we don't yet handle special, so we need to fall back to /bin/mv |
441 |
+ a = spawn([MOVE_BINARY, '-f', src, dest], env=os.environ) |
442 |
+ if a != os.EX_OK: |
443 |
+ writemsg(_("!!! Failed to move special file:\n"), noiselevel=-1) |
444 |
+ writemsg(_("!!! '%(src)s' to '%(dest)s'\n") % \ |
445 |
+ {"src": _unicode_decode(src, encoding=encoding), |
446 |
+ "dest": _unicode_decode(dest, encoding=encoding)}, noiselevel=-1) |
447 |
+ writemsg("!!! %s\n" % a, noiselevel=-1) |
448 |
+ return None # failure |
449 |
+ try: |
450 |
+ if didcopy: |
451 |
+ if stat.S_ISLNK(sstat[stat.ST_MODE]): |
452 |
+ lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) |
453 |
+ else: |
454 |
+ os.chown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) |
455 |
+ os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown |
456 |
+ os.unlink(src) |
457 |
+ except SystemExit as e: |
458 |
+ raise |
459 |
+ except Exception as e: |
460 |
+ print(_("!!! Failed to chown/chmod/unlink in movefile()")) |
461 |
+ print("!!!",dest) |
462 |
+ print("!!!",e) |
463 |
+ return None |
464 |
+ |
465 |
+ # Always use stat_obj[stat.ST_MTIME] for the integral timestamp which |
466 |
+ # is returned, since the stat_obj.st_mtime float attribute rounds *up* |
467 |
+ # if the nanosecond part of the timestamp is 999999881 ns or greater. |
468 |
+ try: |
469 |
+ if hardlinked: |
470 |
+ newmtime = os.stat(dest)[stat.ST_MTIME] |
471 |
+ else: |
472 |
+ # Note: It is not possible to preserve nanosecond precision |
473 |
+ # (supported in POSIX.1-2008 via utimensat) with the IEEE 754 |
474 |
+ # double precision float which only has a 53 bit significand. |
475 |
+ if newmtime is not None: |
476 |
+ os.utime(dest, (newmtime, newmtime)) |
477 |
+ else: |
478 |
+ newmtime = sstat[stat.ST_MTIME] |
479 |
+ if renamefailed: |
480 |
+ # If rename succeeded then timestamps are automatically |
481 |
+ # preserved with complete precision because the source |
482 |
+ # and destination inode are the same. Otherwise, round |
483 |
+ # down to the nearest whole second since python's float |
484 |
+ # st_mtime cannot be used to preserve the st_mtim.tv_nsec |
485 |
+ # field with complete precision. Note that we have to use |
486 |
+ # stat_obj[stat.ST_MTIME] here because the float |
487 |
+ # stat_obj.st_mtime rounds *up* sometimes. |
488 |
+ os.utime(dest, (newmtime, newmtime)) |
489 |
+ except OSError: |
490 |
+ # The utime can fail here with EPERM even though the move succeeded. |
491 |
+ # Instead of failing, use stat to return the mtime if possible. |
492 |
+ try: |
493 |
+ newmtime = os.stat(dest)[stat.ST_MTIME] |
494 |
+ except OSError as e: |
495 |
+ writemsg(_("!!! Failed to stat in movefile()\n"), noiselevel=-1) |
496 |
+ writemsg("!!! %s\n" % dest, noiselevel=-1) |
497 |
+ writemsg("!!! %s\n" % str(e), noiselevel=-1) |
498 |
+ return None |
499 |
+ |
500 |
+ if bsd_chflags: |
501 |
+ # Restore the flags we saved before moving |
502 |
+ if pflags: |
503 |
+ bsd_chflags.chflags(os.path.dirname(dest), pflags) |
504 |
+ |
505 |
+ return newmtime |
506 |
|
507 |
|
508 |
Property changes on: main/trunk/pym/portage/util/movefile.py |
509 |
___________________________________________________________________ |
510 |
Added: svn:keywords |
511 |
+ Id |