~ubuntu-branches/ubuntu/natty/moin/natty-updates

« back to all changes in this revision

Viewing changes to MoinMoin/util/filesys.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-06-22 21:17:13 UTC
  • mfrom: (0.9.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080622211713-fpo2zrq3s5dfecxg
Tags: 1.7.0-3
Simplify /etc/moin/wikilist format: "USER URL" (drop unneeded middle
CONFIG_DIR that was wrongly advertised as DATA_DIR).  Make
moin-mass-migrate handle both formats and warn about deprecation of
the old one.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
"""
3
3
    MoinMoin - File System Utilities
4
4
 
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.
7
7
"""
8
8
 
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
12
11
 
13
12
#############################################################################
14
13
### Misc Helpers
25
24
        if not catchexception:
26
25
            raise
27
26
 
28
 
def makedirs(name, mode=0777):
29
 
    """ Super-mkdir; create a leaf directory and all intermediate ones.
30
 
    
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
33
 
    recursive.
34
 
 
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.
38
 
 
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.
42
 
    """
43
 
    head, tail = os.path.split(name)
44
 
    if not tail:
45
 
        head, tail = os.path.split(head)
46
 
    if head and tail and not os.path.exists(head):
47
 
        makedirs(head, mode)
48
 
        if tail == os.curdir: # xxx/newdir/. exists if xxx/newdir exists
49
 
            return
50
 
    try:
51
 
        os.mkdir(name, mode & config.umask)
52
 
    except OSError, err:
53
 
        if err.errno != errno.EEXIST:
54
 
            raise
55
 
    else:
56
 
        os.chmod(name, mode & config.umask)
57
 
 
58
 
# The original function name is used because it's a modified function
59
 
makeDirs = makedirs
60
 
 
61
27
 
62
28
def rename(oldname, newname):
63
29
    """ Multiplatform rename
75
41
        if os.path.isfile(newname):
76
42
            try:
77
43
                os.remove(newname)
78
 
            except OSError, er:
 
44
            except OSError:
79
45
                pass # let os.rename give us the error (if any)
80
46
    os.rename(oldname, newname)
81
47
 
 
48
def touch(name):
 
49
    if sys.platform == 'win32':
 
50
        import win32file, win32con, pywintypes
 
51
 
 
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
 
57
        mtime = time.gmtime()
 
58
        handle = win32file.CreateFile(name, access, share, None, create,
 
59
                                      win32file.FILE_ATTRIBUTE_NORMAL |
 
60
                                      win32con.FILE_FLAG_BACKUP_SEMANTICS,
 
61
                                      None)
 
62
        try:
 
63
            newTime = pywintypes.Time(mtime)
 
64
            win32file.SetFileTime(handle, newTime, newTime, newTime)
 
65
        finally:
 
66
            win32file.CloseHandle(handle)
 
67
    else:
 
68
        os.utime(name, None)
 
69
 
 
70
def fuid(filename, max_staleness=3600):
 
71
    """ return a unique id for a file
 
72
 
 
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.
 
77
 
 
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.
 
80
 
 
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
 
83
        (file content).
 
84
 
 
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.
 
90
 
 
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
 
99
    """
 
100
    try:
 
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.
 
106
    else:
 
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
 
111
            # trick
 
112
            now = int(time.time())
 
113
            if now >= st.st_mtime + max_staleness:
 
114
                fake_mtime = now
 
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
 
121
                            # sufficient alone
 
122
               fake_mtime,  # trick to workaround file system / platform
 
123
                            # limitations causing permanent trouble
 
124
              )
 
125
    return uid
 
126
 
82
127
 
83
128
def copystat(src, dst):
84
129
    """Copy stat bits from src to dst
117
162
    """
118
163
    names = os.listdir(src)
119
164
    os.mkdir(dst)
120
 
    copystat(src,dst)
 
165
    copystat(src, dst)
121
166
    errors = []
122
167
    for name in names:
123
168
        srcname = os.path.join(src, name)
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'.
163
 
        
 
208
 
164
209
        @param path: string
165
210
        @rtype: string
166
211
        @return the real case of path or None
167
212
        """
168
213
        try:
169
214
            from Carbon import File
 
215
        except ImportError:
 
216
            return None
 
217
        try:
170
218
            return File.FSRef(path).as_pathname()
171
 
        except (ImportError, File.Error):
 
219
        except File.Error:
172
220
            return None
173
221
 
174
222
else:
175
223
 
176
224
    def realPathCase(path):
177
225
        return None
 
226
 
 
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
 
229
def dcdisable():
 
230
    global DCENABLED
 
231
    DCENABLED = 0
 
232
 
 
233
import dircache
 
234
 
 
235
def dclistdir(path):
 
236
    if sys.platform == 'win32' or not DCENABLED:
 
237
        return os.listdir(path)
 
238
    else:
 
239
        return dircache.listdir(path)
 
240
 
 
241
def dcreset():
 
242
    if sys.platform == 'win32' or not DCENABLED:
 
243
        return
 
244
    else:
 
245
        return dircache.reset()