#!/bin/bash
#
# Create a tree of bzr branches for all Debian source packages in a 
# Debian mirror.

set -e

MIRROR=mirror

log() {
    printf "%s %s\n" $(date +%H:%M:%S) "$@"
}

sortversions() {
    if [ "$#" = 0 ]
    then
	echo ""
    elif [ "$#" = 1 ]
    then
	echo "$1"
    elif [ "$#" = 2 ]
    then
	if dpkg --compare-versions "$1" le "$2"
	then
	    echo "$1"
	    echo "$2"
	else
	    echo "$2"
	    echo "$1"
	fi
    else
	v1="$1"
	shift
	versions=$(sortversions "$@")
	sentinel="999999:999999"
	for v in $versions
	do
	    if dpkg --compare-versions "$v1" le "$v"
	    then
		echo "$v1"
		v1="$sentinel"
	    fi
	    echo "$v"
	done
	if [ "$v1" != "$sentinel" ]
	then
	    echo "$v1"
	fi
    fi
}

extractversionsindir() {
    (cd "$MIRROR" && find "$1" -name '*.dsc') |
    sed 's:.*/[^/]*_\(.*\)\.dsc$:\1:'
}

findpooldirs() {
    (cd "$1" && find pool -name '*.dsc') | sed 's:/[^/]*$::' | uniq
}

createbzrdir() {
    # Create the directory, if missing.
    if [ ! -d "$1" ]
    then
        mkdir -p "$1/trunk"
	touch "$1/versions"
	(cd "$1/trunk" && bzr init)
    fi
}

addversion() {
    rm -rf "$1/tmp" "$1/trunk.new" "$1/trunk.old"
    err=$(echo "error-$1.log" | tr / -)
    echo "$@" > "$err"
    dpkglog=$(mktemp)
    if dpkg-source -sn -q -x "$2" "$1/tmp" > "$dpkglog" 2>&1
    then
	cp -a "$1/trunk" "$1/trunk.new"
	rsync -a --delete --exclude=.bzr "$1/tmp/." "$1/trunk.new/."

	bzrlog=$(mktemp)
	if (cd "$1/trunk.new" &&
	    bzr add . &&
	    bzr ignored > "../ignored.tmp" &&
	    while read x y; do bzr add "$x"; done < "../ignored.tmp" &&
	    bzr commit -m "Version $3") > "$bzrlog" 2>&1
	then
	    mv "$1/trunk" "$1/trunk.old"
	    mv "$1/trunk.new" "$1/trunk"
	    rm -rf "$1/trunk.old"
	    echo "$3" >> "$1/versions"
	else
	    log "ERROR: bzr failed" | tee -a "$err"
	    cat "$bzrlog" | tee -a "$err"
	    return
	fi
	rm -f "$bzrlog"
    else
	log "ERROR: dpkg-source failed!" | tee -a "$err"
        cat "$dpkglog" | tee -a "$err"
	return
    fi
    rm -f "$dpkglog" "$err"
    rm -rf "$1/tmp" "$1/trunk.new" "$1/trunk.old" "$1/ignored.tmp"
}

findpooldirs "$MIRROR" |
grep -vf blacklist.txt |
sort |
while read dir
do
    log "$dir"
    createbzrdir "$dir"
    for v in $(sortversions $(extractversionsindir "$dir"))
    do
	if ! grep -Fx "$v" "$dir/versions" > /dev/null
	then
	    log "  New version $v"
    	    package=$(basename "$dir")
    	    dsc="$MIRROR/$dir/${package}_$v.dsc"
	    addversion "$dir" "$dsc" "$v"
	fi
    done
done
