#!/bin/sh
#-*-mode:  sh -*-

# Copyright (c) 2007-2015, Aleksey Cheusov <vle@gmx.net>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
#       copyright notice, this list of conditions and the following
#       disclaimer in the documentation and/or other materials provided
#       with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

############################################################
# user settable variables
: ${PKGSRCDIR:=/usr/pkgsrc}
: ${BMAKE:=/usr/pkg/bin/bmake}
: ${GZIP:=gzip}

############################################################
export LC_ALL=C

set -e

. pipestatus

############################################################
: ${LIBEXECDIR:=/usr/pkg/libexec/psu}

vecho (){
    if test -n "$verbose"; then
	printf "$1" 1>&2
    fi
}

usage (){
    cat 1>&2 <<EOF
pkg_update_src_summary - incrementally updates
package summary from pkgsrc/ tree (in pkg_summary(5) format)

usage: pkg_update_src_summary [OPTIONS]
OPTIONS:
  -h                display this help message
  -f <filename>     obtain PKGPATHs from the specified file
  -i <fields>       list of fields (separated by space character
                    or comma) to be included to the summary,
                    by default full summary is generated
  -d <datadir>      directory where important files are stored,
                    this option is mandatory
  -G                for debugging
  -v                verbose output
EOF
}

pkgs_fn=''
_count_packages=cat

while getopts hf:i:d:Gv f; do
    case "$f" in
	h)  usage; exit 0;;
	f)  pkgs_fn="$OPTARG";;
	i)  PSS_OPTIONS="$PSS_OPTIONS -f $OPTARG";;
	d)  datadir="$OPTARG";;
	G)  debug=1;;
	v)  verbose=1; _count_packages=count_packages;;
	?)  printf "Run pkg_update_src_summary -h for details\n"; exit 2;;
    esac
done
shift `expr $OPTIND - 1`

if test -z "$datadir"; then
    echo 'pkg_update_src_summary: -d option is mandatory' 1>&2
    exit 1
fi

export PSS_OPTIONS

############################################################
cd "$PKGSRCDIR"

mkdir -p "$datadir/tmp"

old_summary="$datadir/pkg_src_summary.txt"
new_summary="$datadir/tmp/pkg_src_summary.txt"

new_pkgs_fn="$datadir/tmp/pkgs"

old_cksums_fn="$datadir/cksums"
new_cksums_fn="$datadir/tmp/cksums"

. "${LIBEXECDIR}/sig_handler.sh"
#on_exit () { true; }
on_exit () { rm -rf "$datadir/tmp"; }

finish (){
    if test -f "$old_cksums_fn"; then
	$GZIP < "$old_cksums_fn" > "$old_cksums_fn.gz"
    fi
    if test -f "$old_summary"; then
	$GZIP < "$old_summary" > "$old_summary.gz"
    fi

    mv "$new_cksums_fn" "$old_cksums_fn"
    mv "$new_summary" "$old_summary"
}

count_packages (){
    awk '{print}
	NF == 0 {printf "\r%d", ++cnt > "/dev/stderr" }
	END {printf "\n" > "/dev/stderr" }' "$@"
}

############################################################
#### Package list
if test -n "$pkgs_fn"; then
    awk '{sub(/#.*/, "")} NF > 0 {print $1}' "$pkgs_fn" > "$new_pkgs_fn"
else
    vecho 'Gathering list of packages...\n'
    pkg_list_all_pkgs > "$new_pkgs_fn"
fi

############################################################
#### Makefiles
vecho 'Scanning makefiles...\n'

makefiles_fn="$datadir/tmp/makefiles"
makefiles_deps_fn="$datadir/tmp/makefiles_deps"
makefiles_useful_fn="$datadir/tmp/makefiles_useful"

awk -v pkgsrcdir="$PKGSRCDIR" '{ print pkgsrcdir "/" $0 "/Makefile" }' \
    "$new_pkgs_fn" > "$makefiles_fn"

makefiles2deps "$makefiles_fn" > "$makefiles_deps_fn"

awk '{h [$1]=0} NF>1 {h [$2]=0} END {for (m in h) print m}' \
    "$makefiles_deps_fn" > "$makefiles_useful_fn"

############################################################
#### cksums
vecho 'Checksums...\n'

if test -s "$makefiles_useful_fn"; then
    runpipe0 \
	xargs cksum < "$makefiles_useful_fn" '|' \
	awk '{print $3, $1, $2}' '|' \
	sort
else
    printf ''
fi > "$new_cksums_fn"

cksums_diff_fn="$datadir/tmp/cksum_diff"
makefiles_updated_fn="$datadir/tmp/makefiles_updated"
updated_pkgs_fn="$datadir/tmp/pkgs_updated"

if ! test -f "$old_summary"; then
    printf '' > "$old_summary"
    printf '' > "$old_cksums_fn"
fi

comm -13 "$old_cksums_fn" "$new_cksums_fn" | \
    awk '{print $1}' > "$cksums_diff_fn"

############################################################
#### updated packages
vecho 'Dependencies between makefiles...\n'

pkg_subgraph_deps -f "$cksums_diff_fn" "$makefiles_deps_fn" \
    > "$makefiles_updated_fn"

awk -v dir="$PKGSRCDIR" '
    BEGIN {l = length(dir)}
    substr($0, 1, l) == dir && match($0, /[^\/]+\/[^\/]+\/Makefile$/) {
        pkgs [substr($0, RSTART, RLENGTH-9)] = 0
    }
    END { for (p in pkgs) print p }' \
    "$makefiles_updated_fn" > "$updated_pkgs_fn"

############################################################
#### updated packages
vecho 'Gathering summaries for '
if test -n "$verbose"; then
    wc -l "$updated_pkgs_fn" | awk '{printf "%s", $1}'
fi
vecho ' package(s)\n'

if test -n "$debug"; then
    echo '==== update pkgs: ====' 1>&2
    cat "$updated_pkgs_fn"
fi

pkg_grep_summary -t strfile PKGPATH "$new_pkgs_fn" \
    < "$old_summary" > "$new_summary"

if test -s "$updated_pkgs_fn"; then
    new_summaries_fn=$datadir/tmp/_new_pkgs

    pkg_grep_summary -v -t strfile PKGPATH "$updated_pkgs_fn" \
	< "$new_summary" > "$new_summary.tmp"
    mv "$new_summary.tmp" "$new_summary"

    pkg_src_summary < "$updated_pkgs_fn" 2>/dev/null |
    $_count_packages > "$new_summaries_fn"

    pkg_summary2bb_pkgs "$new_summaries_fn" > "$new_summaries_fn".tmp
    cat "$new_summaries_fn".tmp >> "$new_summary"
fi

finish
