diff options
author | Endi S. Dewata <edewata@redhat.com> | 2016-12-20 17:59:18 +0100 |
---|---|---|
committer | Endi S. Dewata <edewata@redhat.com> | 2016-12-21 03:04:34 +0100 |
commit | 9822676b7f00cc7e78d42c50c2506a289ed9c1c6 (patch) | |
tree | 0334a13706461c47fb6c4f39c46810ede4fd29cf /base/common/python | |
parent | 843cbeed6ddab8f1883abce47a8c45e0fa14fc5a (diff) | |
download | pki-9822676b7f00cc7e78d42c50c2506a289ed9c1c6.tar.gz pki-9822676b7f00cc7e78d42c50c2506a289ed9c1c6.tar.xz pki-9822676b7f00cc7e78d42c50c2506a289ed9c1c6.zip |
Refactored pki_copytree().
The pki_copytree() has been moved from pkihelper.py into
pki/util.py such that it can be reused in non-deployment
scenarios.
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) |