#!/bin/bash
SOURCE="$0"
source /usr/lib/elive-tools/functions
#EL_REPORTS="1"
#el_make_environment


el_explain_plain(){
    if [[ "${EL_DEBUG}" -ge "2" ]] ; then
        echo -e "$@"
    fi
}

# this tool does caching "to ram" of application/executable and its required libs, can be also used for tracing

main(){
    # pre {{{
    local arg lib sorted is_trace cached_arr

    if [[ "${1}" = "--trace" ]] ; then
        is_trace=1
        shift
    fi

    if [[ "${1}" = "--nice" ]] ; then
        # make precache use the less IO bottleneck as possible, by default
        renice +20 -p $$ 1>/dev/null 2>&1 || true
        ionice -c3 -p$$ 1>/dev/null 2>&1 || true
        shift
    fi


    # }}}
    local files_to_cache_list=""

    # Collect all executables and their libraries
    for arg in "$@"
    do
        local resolved_arg
        if ! [[ -e "$arg" ]] ; then
            resolved_arg="$( command -v "$arg" 2>/dev/null | grep "^/" | head -1 )"
            if ! [[ -e "$resolved_arg" ]] ; then
                el_explain_plain "Skipping non-existent argument: $arg"
                continue
            fi
        else
            resolved_arg="$arg"
        fi

        # Fetch the correct location of the executables if they are symlinked
        resolved_arg="$( readlink -f "$resolved_arg" )"

        # Add executable to list
        if [[ -e "$resolved_arg" ]] ; then
            files_to_cache_list+="${resolved_arg}\n"
        else
            el_explain_plain "Skipping non-existent resolved argument: $resolved_arg (original: $arg)"
            continue # Skip ldd if the main executable doesn't exist after resolving
        fi

        # Add dependant libraries to list
        local lib resolved_lib
        while IFS= read -r lib; do
            # Skip empty lines potentially generated by sed
            [[ -z "$lib" ]] && continue

            if [[ -e "$lib" ]] ; then
                # Get the correct location of the file
                resolved_lib="$( readlink -f "$lib" )"
                if [[ -e "$resolved_lib" ]] ; then
                    files_to_cache_list+="${resolved_lib}\n"
                else
                    el_explain_plain "Skipping non-existent resolved library: $resolved_lib (original: $lib)"
                fi
            else
                el_explain_plain "Skipping non-existent library: $lib"
            fi
        done < <(ldd "${resolved_arg}" 2>/dev/null | sed -e '
            /\//!d;
            /linux-gate/d;
            /=>/ {s/.*=>[[:blank:]]*\([^[:blank:]]*\).*/\1/};
            s/[[:blank:]]*\([^[:blank:]]*\) (.*)/\1/' 2>/dev/null)
    done

    # Create a sorted, unique array of files to cache
    # Using process substitution and readarray (mapfile) for robustness
    readarray -t cached_arr < <(echo -e "${files_to_cache_list}" | sort -u)

    # el_explain_plain "cache list ready"

    # Precache final result
    local sorted
    for sorted in "${cached_arr[@]}"
    do
        [[ -z "$sorted" ]] && continue
        if ((is_trace)) ; then
            echo "$sorted"
        else
            el_explain_plain "caching ${sorted##*/}"
        fi
        # precache
        cat "$sorted" > /dev/null 2>&1
    done

}

#
#  MAIN
#
main "$@"

