Copy directory source to be a subdirectory of target if it matches the required_digest.
manifest_data is normally source/.manifest. source and manifest_data are not trusted
(will typically be under the control of another user).
The copy is first done to a temporary directory in target, then renamed to the final name
only if correct. Therefore, an invalid 'target/required_digest' will never exist.
A successful return means than target/required_digest now exists (whether we created it or not).

00238 :
"""Copy directory source to be a subdirectory of target if it matches the required_digest. manifest_data is normally source/.manifest. source and manifest_data are not trusted (will typically be under the control of another user). The copy is first done to a temporary directory in target, then renamed to the final name only if correct. Therefore, an invalid 'target/required_digest' will never exist. A successful return means than target/required_digest now exists (whether we created it or not)."""import tempfile, shutil
from logging import info
alg, digest_value = splitID(required_digest)
if isinstance(alg, OldSHA1):
raise SafeException("Sorry, the 'sha1' algorithm does not support copying.")
digest = alg.new_digest()
digest.update(manifest_data)
manifest_digest = alg.getID(digest)
if manifest_digest != required_digest:
raise zerostore.BadDigest("Manifest has been tampered with!\n""Manifest digest: " + manifest_digest + "\n""Directory name : " + required_digest)
target_impl = os.path.join(target, required_digest)
if os.path.isdir(target_impl):
info("Target directory '%s' already exists", target_impl)
return# We've checked that the source's manifest matches required_digest, so it# is what we want. Make a list of all the files we need to copy...
wanted = _parse_manifest(manifest_data)
tmpdir = tempfile.mkdtemp(prefix = 'tmp-copy-', dir = target)
try:
_copy_files(alg, wanted, source, tmpdir)
if wanted:
raise SafeException('Copy failed; files missing from source:\n- ' +
'\n- '.join(wanted.keys()))
# Check that the copy is correct
actual_digest = alg.getID(add_manifest_file(tmpdir, alg))
if actual_digest != required_digest:
raise SafeException(("Copy failed; double-check of target gave the wrong digest.\n""Unless the target was modified during the copy, this is a BUG\n""in 0store and should be reported.\n""Expected: %s\n""Actual: %s") % (required_digest, actual_digest))
os.rename(tmpdir, target_impl)
# TODO: catch already-exists, delete tmpdir and return successexcept:
info("Deleting tmpdir '%s'" % tmpdir)
shutil.rmtree(tmpdir)
raisedef _parse_manifest(manifest_data):