3
3
MoinMoin - File System Utilities
5
@copyright: 2002 by J�rgen Hermann <jh@web.de>
5
@copyright: 2002 Juergen Hermann <jh@web.de>
6
6
@license: GNU GPL, see COPYING for details.
9
import sys, os, shutil, errno
9
import sys, os, shutil, time
10
10
from stat import S_ISDIR, ST_MODE, S_IMODE
11
from MoinMoin import config
13
12
#############################################################################
25
24
if not catchexception:
28
def makedirs(name, mode=0777):
29
""" Super-mkdir; create a leaf directory and all intermediate ones.
31
Works like mkdir, except that any intermediate path segment (not
32
just the rightmost) will be created if it does not exist. This is
35
This is modified version of the os.makedirs from Python 2.4. We add
36
explicit chmod call after the mkdir call. Fixes some practical
37
permission problems on Linux.
39
TODO: we use os.umask() now so we usually don't need explicit chmod any
40
more. Check all callers os makedirs/makeDirs and also py2.3+
41
stdlib implementation and maybe remove this function here.
43
head, tail = os.path.split(name)
45
head, tail = os.path.split(head)
46
if head and tail and not os.path.exists(head):
48
if tail == os.curdir: # xxx/newdir/. exists if xxx/newdir exists
51
os.mkdir(name, mode & config.umask)
53
if err.errno != errno.EEXIST:
56
os.chmod(name, mode & config.umask)
58
# The original function name is used because it's a modified function
62
28
def rename(oldname, newname):
63
29
""" Multiplatform rename
75
41
if os.path.isfile(newname):
79
45
pass # let os.rename give us the error (if any)
80
46
os.rename(oldname, newname)
49
if sys.platform == 'win32':
50
import win32file, win32con, pywintypes
52
access = win32file.GENERIC_WRITE
53
share = (win32file.FILE_SHARE_DELETE |
54
win32file.FILE_SHARE_READ |
55
win32file.FILE_SHARE_WRITE)
56
create = win32file.OPEN_EXISTING
58
handle = win32file.CreateFile(name, access, share, None, create,
59
win32file.FILE_ATTRIBUTE_NORMAL |
60
win32con.FILE_FLAG_BACKUP_SEMANTICS,
63
newTime = pywintypes.Time(mtime)
64
win32file.SetFileTime(handle, newTime, newTime, newTime)
66
win32file.CloseHandle(handle)
70
def fuid(filename, max_staleness=3600):
71
""" return a unique id for a file
73
Using just the file's mtime to determine if the file has changed is
74
not reliable - if file updates happen faster than the file system's
75
mtime granularity, then the modification is not detectable because
76
the mtime is still the same.
78
This function tries to improve by using not only the mtime, but also
79
other metadata values like file size and inode to improve reliability.
81
For the calculation of this value, we of course only want to use data
82
that we can get rather fast, thus we use file metadata, not file data
85
Note: depending on the operating system capabilities and the way the
86
file update is done, this function might return the same value
87
even if the file has changed. It should be better than just
88
using file's mtime though.
89
max_staleness tries to avoid the worst for these cases.
91
@param filename: file name of the file to look at
92
@param max_staleness: if a file is older than that, we may consider
93
it stale and return a different uid - this is a
94
dirty trick to work around changes never being
95
detected. Default is 3600 seconds, use None to
96
disable this trickery. See below for more details.
97
@return: an object that changes value if the file changed,
98
None is returned if there were problems accessing the file
101
st = os.stat(filename)
102
except (IOError, OSError):
103
uid = None # for permanent errors on stat() this does not change, but
104
# having a changing value would be pointless because if we
105
# can't even stat the file, it is unlikely we can read it.
107
fake_mtime = int(st.st_mtime)
108
if not st.st_ino and max_staleness:
109
# st_ino being 0 likely means that we run on a platform not
110
# supporting it (e.g. win32) - thus we likely need this dirty
112
now = int(time.time())
113
if now >= st.st_mtime + max_staleness:
115
uid = (st.st_mtime, # might have a rather rough granularity, e.g. 2s
116
# on FAT and might not change on fast updates
117
st.st_ino, # inode number (will change if the update is done
118
# by e.g. renaming a temp file to the real file).
119
# not supported on win32 (0 ever)
120
st.st_size, # likely to change on many updates, but not
122
fake_mtime, # trick to workaround file system / platform
123
# limitations causing permanent trouble
83
128
def copystat(src, dst):
84
129
"""Copy stat bits from src to dst
160
205
HFS and HFS+ file systems, are case preserving but case
161
206
insensitive. You can't have 'file' and 'File' in the same
162
207
directory, but you can get the real name of 'file'.
164
209
@param path: string
166
211
@return the real case of path or None
169
214
from Carbon import File
170
218
return File.FSRef(path).as_pathname()
171
except (ImportError, File.Error):
176
224
def realPathCase(path):
227
# dircache stuff seems to be broken on win32 (at least for FAT32, maybe NTFS)
228
DCENABLED = 1 # set to 0 to disable dirchache usage
236
if sys.platform == 'win32' or not DCENABLED:
237
return os.listdir(path)
239
return dircache.listdir(path)
242
if sys.platform == 'win32' or not DCENABLED:
245
return dircache.reset()