Based on two downloaded files in the working directory,
    the student submission and the validation package,
    the working directory is prepared.

    We unpack student submission first, so that teacher files overwrite
    them in case.

    When the student submission is a single directory, we change the
    working directory and go directly into it, before dealing with the
    validator stuff.

    If unrecoverable errors happen, such as an empty student archive,
    a JobException is raised.

def prepare_working_directory(job, submission_path, validator_path):
    '''
    Based on two downloaded files in the working directory,
    the student submission and the validation package,
    the working directory is prepared.

    We unpack student submission first, so that teacher files overwrite
    them in case.

    When the student submission is a single directory, we change the
    working directory and go directly into it, before dealing with the
    validator stuff.

    If unrecoverable errors happen, such as an empty student archive,
    a JobException is raised.
    '''
    # Safeguard for fail-fast in disk full scenarios on the executor

    dusage = shutil.disk_usage(job.working_dir)
    if dusage.free < 1024 * 1024 * 50:   # 50 MB
        info_student = "Internal error with the validator. Please contact your course responsible."
        info_tutor = "Error: Execution cancelled, less then 50MB of disk space free on the executor."
        logger.error(info_tutor)
        raise JobException(info_student=info_student, info_tutor=info_tutor)

    submission_fname = os.path.basename(submission_path)
    validator_fname = os.path.basename(validator_path)

    # Un-archive student submission
    single_dir, did_unpack = unpack_if_needed(job.working_dir, submission_path)
    job.student_files = os.listdir(job.working_dir)
    if did_unpack:
        job.student_files.remove(submission_fname)

    # Fail automatically on empty student submissions
    if len(job.student_files) is 0:
        info_student = "Your compressed upload is empty - no files in there."
        info_tutor = "Submission archive file has no content."
        logger.error(info_tutor)
        raise JobException(info_student=info_student, info_tutor=info_tutor)

    # Handle student archives containing a single directory with all data
    if single_dir:
        logger.warning(
            "The submission archive contains only one directory. Changing working directory.")
        # Set new working directory
        job.working_dir = job.working_dir + single_dir + os.sep
        # Move validator package there
        shutil.move(validator_path, job.working_dir)
        validator_path = job.working_dir + validator_fname
        # Re-scan for list of student files
        job.student_files = os.listdir(job.working_dir)

    # The working directory now only contains the student data and the downloaded
    # validator package.
    # Update the file list accordingly.
    job.student_files.remove(validator_fname)
    logger.debug("Student files: {0}".format(job.student_files))

    # Unpack validator package
    single_dir, did_unpack = unpack_if_needed(job.working_dir, validator_path)
    if single_dir:
        info_student = "Internal error with the validator. Please contact your course responsible."
        info_tutor = "Error: Directories are not allowed in the validator archive."
        logger.error(info_tutor)
        raise JobException(info_student=info_student, info_tutor=info_tutor)

    if not os.path.exists(job.validator_script_name):
        if did_unpack:
            # The download was an archive, but the validator was not inside.
            # This is a failure of the tutor.
            info_student = "Internal error with the validator. Please contact your course responsible."
            info_tutor = "Error: Missing validator.py in the validator archive."
            logger.error(info_tutor)
            raise JobException(info_student=info_student,
                               info_tutor=info_tutor)
        else:
            # The download is already the script, but has the wrong name
            logger.warning("Renaming {0} to {1}.".format(
                validator_path, job.validator_script_name))
            shutil.move(validator_path, job.validator_script_name)