#!/bin/sh
#
# mkjigsnap
#
# (c) 2004 Steve McIntyre
#
# Server-side wrapper; run this on a machine with a mirror to set up
# the snapshots for jigit
#
# GPL v2 - see COPYING 
#
# Some things needed:
#   location of the mirror
#   the keyword to look for (e.g. Debian)
#   the snapshot dirname (e.g. today's date)
#   the jigdo files
# Example:
# ./mkjigsnap -m /tmp/mirror \
#      -k Debian -k Non-US \
#      -d 20041017 \
#      jigdo1 jigdo2 jigdo3 ...

STARTDATE=`date`

while [ $# -gt 0 ]
do
    case "$1"x in
        "-m"x)
            shift
            MIRROR=$1
            shift
            ;;
        "-d"x)
            shift
            DIRNAME=$1
            shift
            ;;
        "-j"x)
			shift
			JIGDOLIST=$1
			shift
			;;
        "-t"x)
            shift
            TF_TMPDIR="--directory $1"
            SORT_TMPDIR="-T $1"
            shift
            ;;
        *)
            JIGDOS="$JIGDOS $1"
            shift
            ;;
    esac
done

if [ "$MIRROR"x = ""x ] ; then
    echo "You must specify the location of the mirror!"
    exit 1
fi
    
if [ "$DIRNAME"x = ""x ] ; then
    echo "You must specify the snapshot directory name!"
    exit 1
fi
    
if [ "$JIGDOS"x = ""x ] ; then
    if [ "$JIGDOLIST"x = ""x ] ; then
		echo "You must specify some jigdo files!"
		exit 1
	fi
fi

TMPFILE=`tempfile $TF_TMPDIR`
if [ "$JIGDOLIST"x != ""x ] ; then
	for JIGDO in `cat $JIGDOLIST`
	do
		zcat -f $JIGDO | sed -n "s/^.*Debian://gp" >> $TMPFILE
	done
fi

if [ "$JIGDOS"x != ""x ] ; then 
	zcat -f $JIGDOS | sed -n "s/^.*Debian://gp" >> $TMPFILE
fi

LISTDONEDATE=`date`

TMPFILE1=`tempfile $TF_TMPDIR`
TOTAL_FILES=`wc -l < $TMPFILE`

cat $TMPFILE | sort -u $SORT_TMPDIR > $TMPFILE1

SORTDONEDATE=`date`
NUM_FILES=`wc -l < $TMPFILE1`

mv -f $TMPFILE1 $TMPFILE
  
NUM=`cat $TMPFILE | wc -l`

LINKS_DONE=0
(echo $NUM; echo $MIRROR; echo $DIRNAME; cat $TMPFILE ) | perl -we '

    use File::Basename;
	use File::Find;
    my $num;
    my $mirrorpath;
    my $outdir;
    my $dirname;
    my $filename;
    my $done = 0;
	my $failed = 0;
	my @file_list;
    my $old_deleted = 0;
    my $link;
    $| = 1;

    # Make a dir tree
    sub mkdirs {
        my $input = shift;
        my $dir;
        my @components;
        my $need_slash = 0;

        if (! -d $input) {
            @components = split /\//,$input;
            foreach $component (@components) {
                if ($need_slash) {
                    $dir = join ("/", $dir, $component);
                } else {
                    $dir = $component;
                    $need_slash = 1;
                }
                if (! -d $dir) {
                    mkdir $dir;
                }
            }
        }
    }        

	sub delete_redundant {
		my $ref;

		if (-f) {
			$ref = $file_list{$File::Find::name};
			if (!defined($ref)) {
				unlink($File::Find::name);
				$old_deleted++;
				if ( !($old_deleted % 1000) ) {
					print "$old_deleted\n";
				}
			}
		}
	}

    while (<>) {
        chomp;

        if (!defined($num)) {
            $num = $_;
            next;
        }
        if (!defined($mirrorpath)) {
            $mirrorpath = $_;
            next;
        }
        if (!defined($outdir)) {
            $outdir = $_;
            print "Linking $num files from $mirrorpath to $outdir\n";
            next;
        }

        $outfile = $outdir . "/" . $_;
		$file_list{$outfile}++;
        if (! -e $outfile) {
            $dirname = dirname($_);
            $filename = basename($_);

            mkdirs($outdir . "/" . $dirname);
	    my $link_ok = 0;
	    foreach $mirror (split /:/,$mirrorpath) {
		$infile = $mirror . "/" . $_;
		if (-l $infile) {
		    $link = readlink($infile);
		    if ($link =~ m#^/#) {
		        $infile = $link;
                    } else {
                        $infile = dirname($infile) . "/" . $link;
                    }
                }
                $outfile = $outdir . "/" . $_;
                if (link ($infile, $outfile)) {
		    $link_ok = 1;
		    last;
		}
		$infile = $mirror . "/" . $filename;
#		print "Falling back to $infile\n";
                if (link ($infile, $outfile)) {
		    $link_ok = 1;
		    last;
		}		
            }
	    if ($link_ok == 0) {
	        print "\nFailed to create link $outfile\n";
	        $failed++;
            }
        }
        $done++;
	if ( !($done % 1000) ) {
		print "$done/$num\n";
	    }
    }
	print "  Finished: $done/$num, $failed failed\n\n";

	# Now walk the tree and delete files that we no longer need
	print "Scanning for now-redundant files\n";
	find(\&delete_redundant, $outdir);
	print "  Finished: $old_deleted old files removed\n";
'

rm -f $TMPFILE
echo

echo "$STARTDATE: startup"
echo "$LISTDONEDATE: $TOTAL_FILES found"
echo "$SORTDONEDATE: $NUM_FILES after sorting"
echo `date`": mkjigsnap finished successfully"