# -*- coding: iso-8859-1 -*-
"""
    MoinMoin - File System Utilities

    @copyright: 2002 by Jürgen Hermann <jh@web.de>
    @license: GNU GPL, see COPYING for details.
"""

import sys, os
from MoinMoin import config

#############################################################################
### Misc Helpers
#############################################################################

def makeDirs(name, mode=0777):
    """ Like os.makedirs(), but with explicit chmod() calls.
        Fixes some practical permission problems on Linux.
    """
    head, tail = os.path.split(name)
    if not tail:
        head, tail = os.path.split(head)
    if head and tail and not os.path.exists(head):
        makeDirs(head, mode)

    os.mkdir(name, mode & config.umask)
    os.chmod(name, mode & config.umask)


def rename(oldname, newname):
    ''' Multiplatform rename

    Needed because win32 rename is not POSIX compliant, and does not
    remove target file if it exists.

    Problem: this "rename" is not atomic any more on win32.

    FIXME: What about rename locking? we can have a lock file in the
    page directory, named: PageName.lock, and lock this file before we
    rename, then unlock when finished.
    '''
    if os.name == 'nt':
        if os.path.isfile(newname):
            try:
                os.remove(newname)
            except OSError, er:
                pass # let os.rename give us the error (if any)
    return os.rename(oldname, newname)


def copystat(src, dst):
    """Copy stat bits from src to dst

    This should be used when shutil.copystat would be used on directories
    on win32 because win32 does not support utime() for directories.

    According to the official docs written by Microsoft, it returns ENOACCES if the
    supplied filename is a directory. Looks like a trainee implemented the function.
    """
    from stat import S_ISDIR, ST_MODE, S_IMODE
    if sys.platform == 'win32' and S_ISDIR(os.stat(dst)[ST_MODE]):
        if os.name == 'nt':
            st = os.stat(src)
            mode = S_IMODE(st[ST_MODE])
            if hasattr(os, 'chmod'):
                os.chmod(dst, mode)
        #else: pass # we are on Win9x,ME - no chmod here
    else:
        import shutil
        shutil.copystat(src, dst)


def copytree(src, dst, symlinks=False):
    """Recursively copy a directory tree using copy2().

    The destination directory must not already exist.
    If exception(s) occur, an Error is raised with a list of reasons.

    If the optional symlinks flag is true, symbolic links in the
    source tree result in symbolic links in the destination tree; if
    it is false, the contents of the files pointed to by symbolic
    links are copied.

    In contrary to shutil.copytree, this version also copies directory
    stats, not only file stats.

    """
    names = os.listdir(src)
    os.mkdir(dst)
    copystat(src,dst)
    errors = []
    for name in names:
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        try:
            if symlinks and os.path.islink(srcname):
                linkto = os.readlink(srcname)
                os.symlink(linkto, dstname)
            elif os.path.isdir(srcname):
                copytree(srcname, dstname, symlinks)
            else:
                import shutil
                shutil.copy2(srcname, dstname)
            # XXX What about devices, sockets etc.?
        except (IOError, os.error), why:
            errors.append((srcname, dstname, why))
    if errors:
        raise EnvironmentError, errors

# Code could come from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65203

# we currently do not support locking
LOCK_EX = LOCK_SH = LOCK_NB = 0

def lock(file, flags):
    raise NotImplementedError

def unlock(file):
    raise NotImplementedError

