Returns the differences between two snapshots

    config
        Configuration name.

    filename
        if not provided the showing differences between snapshots for
        all "text" files

    num_pre
        first snapshot ID to compare. Default is last snapshot

    num_post
        last snapshot ID to compare. Default is 0 (current state)

    CLI Example:

    .. code-block:: bash

        salt '*' snapper.diff
        salt '*' snapper.diff filename=/var/log/snapper.log num_pre=19 num_post=20

def diff(config='root', filename=None, num_pre=None, num_post=None):
    '''
    Returns the differences between two snapshots

    config
        Configuration name.

    filename
        if not provided the showing differences between snapshots for
        all "text" files

    num_pre
        first snapshot ID to compare. Default is last snapshot

    num_post
        last snapshot ID to compare. Default is 0 (current state)

    CLI Example:

    .. code-block:: bash

        salt '*' snapper.diff
        salt '*' snapper.diff filename=/var/log/snapper.log num_pre=19 num_post=20
    '''
    try:
        pre, post = _get_num_interval(config, num_pre, num_post)

        files = changed_files(config, pre, post)
        if filename:
            files = [filename] if filename in files else []

        SUBVOLUME = list_configs()[config]['SUBVOLUME']
        pre_mount = snapper.MountSnapshot(config, pre, False) if pre else SUBVOLUME
        post_mount = snapper.MountSnapshot(config, post, False) if post else SUBVOLUME

        files_diff = dict()
        for filepath in [filepath for filepath in files if not os.path.isdir(filepath)]:

            _filepath = filepath
            if filepath.startswith(SUBVOLUME):
                _filepath = filepath[len(SUBVOLUME):]

            # Just in case, removing possible double '/' from the final file paths
            pre_file = os.path.normpath(pre_mount + "/" + _filepath).replace("//", "/")
            post_file = os.path.normpath(post_mount + "/" + _filepath).replace("//", "/")

            if os.path.isfile(pre_file):
                pre_file_exists = True
                with salt.utils.files.fopen(pre_file) as rfh:
                    pre_file_content = [salt.utils.stringutils.to_unicode(_l)
                                        for _l in rfh.readlines()]
            else:
                pre_file_content = []
                pre_file_exists = False

            if os.path.isfile(post_file):
                post_file_exists = True
                with salt.utils.files.fopen(post_file) as rfh:
                    post_file_content = [salt.utils.stringutils.to_unicode(_l)
                                         for _l in rfh.readlines()]
            else:
                post_file_content = []
                post_file_exists = False

            if _is_text_file(pre_file) or _is_text_file(post_file):
                files_diff[filepath] = {
                    'comment': "text file changed",
                    'diff': ''.join(difflib.unified_diff(pre_file_content,
                                                         post_file_content,
                                                         fromfile=pre_file,
                                                         tofile=post_file))}

                if pre_file_exists and not post_file_exists:
                    files_diff[filepath]['comment'] = "text file deleted"
                if not pre_file_exists and post_file_exists:
                    files_diff[filepath]['comment'] = "text file created"

            elif not _is_text_file(pre_file) and not _is_text_file(post_file):
                # This is a binary file
                files_diff[filepath] = {'comment': "binary file changed"}
                if pre_file_exists:
                    files_diff[filepath]['old_sha256_digest'] = __salt__['hashutil.sha256_digest'](''.join(pre_file_content))
                if post_file_exists:
                    files_diff[filepath]['new_sha256_digest'] = __salt__['hashutil.sha256_digest'](''.join(post_file_content))
                if post_file_exists and not pre_file_exists:
                    files_diff[filepath]['comment'] = "binary file created"
                if pre_file_exists and not post_file_exists:
                    files_diff[filepath]['comment'] = "binary file deleted"

        if pre:
            snapper.UmountSnapshot(config, pre, False)
        if post:
            snapper.UmountSnapshot(config, post, False)
        return files_diff
    except dbus.DBusException as exc:
        raise CommandExecutionError(
            'Error encountered while showing differences between snapshots: {0}'
            .format(_dbus_exception_to_reason(exc, locals()))
        )