diff options
Diffstat (limited to 'base/common/python')
-rw-r--r-- | base/common/python/pki/util.py | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/base/common/python/pki/util.py b/base/common/python/pki/util.py index 95a367055..8a75ff6f5 100644 --- a/base/common/python/pki/util.py +++ b/base/common/python/pki/util.py @@ -26,6 +26,11 @@ Module containing utility functions and classes for the Dogtag python code from __future__ import absolute_import import os import shutil +from shutil import Error +try: + from shutil import WindowsError # pylint: disable=E0611 +except ImportError: + WindowsError = None def copy(source, dest): @@ -136,3 +141,74 @@ def customize_file(input_file, output_file, params): for src, target in params.items(): line = line.replace(src, target) outfile.write(line) + + +def copytree(src, dst, symlinks=False, ignore=None): + """ + Recursively copy a directory tree using copy2(). + + PATCH: This code was copied from 'shutil.py' and patched to + allow 'The destination directory to 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. + + The optional ignore argument is a callable. If given, it + is called with the `src` parameter, which is the directory + being visited by copytree(), and `names` which is the list of + `src` contents, as returned by os.listdir(): + + callable(src, names) -> ignored_names + + Since copytree() is called recursively, the callable will be + called once for each directory that is copied. It returns a + list of names relative to the `src` directory that should + not be copied. + + Consider this example code rather than the ultimate tool. + """ + names = os.listdir(src) + if ignore is not None: + ignored_names = ignore(src, names) + else: + ignored_names = set() + + # PATCH: ONLY execute 'os.makedirs(dst)' if the top-level + # destination directory does NOT exist! + if not os.path.exists(dst): + os.makedirs(dst) + errors = [] + for name in names: + if name in ignored_names: + continue + 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, ignore) + else: + # Will raise a SpecialFileError for unsupported file types + shutil.copy2(srcname, dstname) + # catch the Error from the recursive copytree so that we can + # continue with other files + except Error as err: + errors.extend(err.args[0]) + except EnvironmentError as why: + errors.append((srcname, dstname, str(why))) + try: + shutil.copystat(src, dst) + except OSError as why: + if WindowsError is not None and isinstance(why, WindowsError): + # Copying file access times may fail on Windows + pass + else: + errors.extend((src, dst, str(why))) + if errors: + raise Error(errors) |