1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
from os import altsep, chmod, mkdir, remove, sep, stat, walk
from os.path import dirname, exists, isdir, isfile, islink, join as joinpath
from shutil import copyfile
try:
from os import symlink
except ImportError:
def symlink(src, dst): # pylint: disable-msg=W0613
raise OSError('This platform does not support symbolic links')
def scanTree(baseDir):
'''Scans files and directories from the given base directory and iterates
through the paths of the files and directories it finds; these paths are
relative to the base directory.
Directories will always be returned before any of the files they contain.
The base directory itself is not returned.
Hidden files and directories are not returned.
All paths returned use the OS native separator character (os.sep),
regardless of which separator characters were used in the arguments.
Raises OSError if there is an I/O error scanning the base directory.
'''
if altsep is not None:
# Make sure all paths use the OS native separator, so we can safely
# compare paths and have consistent error messages.
baseDir = baseDir.replace(altsep, sep)
baseDir = baseDir.rstrip(sep)
if not isdir(baseDir):
raise OSError('Directory "%s" does not exist' % baseDir)
def escalate(ex):
raise OSError(
'Error scanning directory entry "%s": %s' % (ex.filename, ex)
)
for dirPath, dirNames, fileNames in walk(baseDir, onerror = escalate):
# Skip hidden directories.
# We are deleting items from the list we are iterating over; that
# requires some extra care.
index = 0
while index < len(dirNames):
if dirNames[index].startswith('.'):
del dirNames[index]
else:
index += 1
# Skip hidden files.
fileNames = [ name for name in fileNames if not name.startswith('.') ]
if dirPath == baseDir:
relDir = ''
else:
assert dirPath.startswith(baseDir + sep), dirPath
relDir = dirPath[len(baseDir) + 1 : ]
yield relDir
for fileName in fileNames:
yield joinpath(relDir, fileName)
def installDir(path):
'''Creates the given path, excluding parent directories.
The directory is created with permissions such that all users can read what
is installed and only the owner can modify what is installed.
If the given path already exists, nothing happens.
'''
if not isdir(path):
# We have to do chmod() separately because the "mode" argument of
# mkdir() is modified by umask.
mkdir(path)
chmod(path, 0o755)
def _installDirsRec(path):
'''Like installDirs(), except that "altsep" is not supported as directory
separator in "path".
'''
path = path.rstrip(sep)
if path and not isdir(path):
index = path.rfind(sep)
if index != -1:
_installDirsRec(path[ : index])
mkdir(path)
chmod(path, 0o755)
def installDirs(path):
'''Creates the given path, including any parent directories if necessary.
Any newly created directories are created with permissions such that all
users can read what is installed and only the owner can modify what is
installed.
If the given path already exists, nothing happens.
'''
if altsep is not None:
path = path.replace(altsep, sep)
_installDirsRec(path)
def installFile(srcPath, destPath):
'''Copies a file from the given source path to the given destination path.
The destination file is created with permissions such that all users can
read (and execute, if appropriate) what is installed and only the owner
can modify what is installed.
Raises OSError if there is a problem reading or writing files.
'''
copyfile(srcPath, destPath)
chmod(destPath, 0o755 if (stat(srcPath).st_mode & 0o100) else 0o644)
def installSymlink(target, link):
'''Creates a symbolic link with the given name to the given target.
If a symbolic link with the given name already exists, it is replaced.
If a different file type with the given name already exists, OSError is
raised.
Also raises OSError if this platform lacks os.symlink().
'''
if islink(link):
remove(link)
symlink(target, link)
def installTree(srcDir, destDir, paths):
'''Copies files and directories from the given source directory to the
given destination directory. The given paths argument is a sequence of
paths relative to the source directory; only those files and directories
are copied. The scanTree() function is suitable to provide paths.
Files and directories are created with permissions such that all users can
read (and execute, if appropriate) what is installed and only the owner
can modify what is installed.
Raises OSError if there is a problem reading or writing files or
directories.
'''
if not isdir(destDir):
raise OSError('Destination directory "%s" does not exist' % destDir)
for relPath in paths:
if altsep is not None:
relPath = relPath.replace(altsep, sep)
srcPath = joinpath(srcDir, relPath)
destPath = joinpath(destDir, relPath)
if islink(srcPath):
print('Skipping symbolic link:', srcPath)
elif isdir(srcPath):
_installDirsRec(destPath)
elif isfile(srcPath):
_installDirsRec(dirname(destPath))
installFile(srcPath, destPath)
elif exists(srcPath):
print('Skipping unknown kind of file system entry:', srcPath)
else:
print('Skipping non-existing path:', srcPath)
|