#!/bin/sh

set -e

export PATH=/bin:/usr/bin

quote_url ()
{
    printf "%s\n" "$@" | awk '
    BEGIN {
        for (i = 0; i < 255; i++) {
         _char_table[sprintf("%c", i)] = i
        }
    }

    {
        str = $0
        while(match(str, /[^0-9a-zA-Z.+-]/)) {
            quoted = quoted substr(str, 0, RSTART - 1) \
                sprintf("%%%02X", _char_table[substr(str, RSTART, RLENGTH)])
            str = substr(str, RSTART + RLENGTH)
        }
        quoted = quoted str
        print quoted
    }
    '
}

usage ()
{
    printf "Usage: %s [-f files|packages|full] pattern url|version\n" \
        "${0##*/}" >&2
}

while getopts "f:h?v" opts; do
    case ${opts} in
        f)  format="${OPTARG}"
            ;;
        v)  verbose=true
            ;;
        h|\?)
            usage
            exit 0
            ;;
        *)  usage
            exit 2
            ;;
    esac
done
shift $((${OPTIND} - 1))

if [ $# -ne 2 ]; then
    usage
    exit 2
fi

content_pattern="$1"
case $2 in
    http://*|ftp://*)   url="${2%/}/ARCHIVES.gz"
                        ;;
    11.[123])           url="http://download.opensuse.org/distribution/${2}/repo/oss/ARCHIVES.gz"
                        ;;
    Factory)            url="http://download.opensuse.org/factory/repo/oss/ARCHIVES.gz"
                        ;;
esac
quoted_url="$(quote_url "${url}")"
format="${format:-full}"
verbose="${verbose:-false}"
cachedir="${HOME}/.${0##*/}_cache"
$verbose && curl_cmd="curl" || curl_cmd="curl --silent"

[ -d "${cachedir}" ] || mkdir -p "${cachedir}"
[ -f "${cachedir}/cache_index.txt" ] || touch "${cachedir}/cache_index.txt"

# try to get modified date from cache index
modified_date="$(awk -v "url=${url}" '$0 == url { getline; print; exit }' "${cachedir}/cache_index.txt")"

# retrive ARCHIVES.gz for repo
if ! ${curl_cmd} --fail --show-error --location \
    --dump-header "${cachedir}/${quoted_url}_headers.txt" "${url}" \
    --time-cond "${modified_date:-Thu, 01 Jan 1970 00:00:00 GMT}" \
    -o "${cachedir}/${quoted_url}"; then
    rm "${cachedir}/${quoted_url}_headers.txt" >/dev/null 2>&1 || :
    exit 1
fi

# update cache index
last_modified="$(sed -n '/^Last-Modified: /{s/Last-Modified: //;s/\r//g;h};${g;p}' "${cachedir}/${quoted_url}_headers.txt")"
if [ -n "${last_modified}" ]; then
    awk -v "url=${url}" \
        -v "last_modified=${last_modified}" '
!updated && $0 == url {
    getline
    next
}

{ print }

END {
    print url
    print last_modified
}
' "${cachedir}/cache_index.txt" > "${cachedir}/cache_index.txt.tmp"
    mv "${cachedir}/cache_index.txt.tmp" "${cachedir}/cache_index.txt"
fi

# search
gzip -c -d "${cachedir}/${quoted_url}" | \
    awk -v "content_pattern=${content_pattern}" -v "format=${format}" -v "url=${url}" '
BEGIN {
    print "Packages matching \"" content_pattern "\" (" url "):"
}

$0 ~ content_pattern {
    content = $0
    if (! sub(/^[^ ]+[ \t]+[^ ]+[ \t]+[^ ]+[ \t]+[^ ]+[ \t]+[^ ]+[ \t]+[^ ]+[ \t]+[^ ]+[ \t]+[^ ]+[ \t]+[^ ]+[ \t]+/, "", content)) {
        next
    }

    if (content ~ content_pattern) {
        line = $0
        package = $1
        sub(/^.*\//, "", package)
        sub(/:$/, "", package)
        if (format == "files") {
            printf("%s: %s\n", package, content)
        } else if (format == "packages") {
            if (package in matched_packages) {
                next
            } else {
                print package
                matched_packages[package]++
            }
        } else {
            sub(/^[^ ]+[ \t]+/, "", line)
            printf("%s: %s\n", package, line)
        }
    }
    next
}
'
