#!/usr/bin/perl
# ucampas-navtest -- test if a list of *-b.html files are in the same NavTree
#
# https://www.cl.cam.ac.uk/local/sys/web/ucampas/
#
# Markus Kuhn -- https://www.cl.cam.ac.uk/~mgk25/

# this software requires Perl 5.14 or newer
use 5.014;  # implies use strict;

use FindBin qw($RealBin);     # find directory where this file is located ...
use lib $RealBin, "$RealBin/perl-PlexTree";     # ... and add it to @INC
use NavTree;
use PlexTree;

# Parse the command-line options

my $usage = <<'EOT';
ucampas-navtest -- test if a list of *-b.html files are all in the same NavTree

Usage:

  ucampas-navtest [options] {files}

Examples:

  ucampas-navtest *-b.{html,php}
  find -name '*-b.html' -print0 | ucampas-navtest -0
  find -name .svn -prune -false -o -iregex '.*-b\.\(html?\|php\)' -print0 | \
    ucampas-navtest -0

Normal options:

  -s     Read a list of files to be checked as linefeed-terminated strings
         from stdin

  -0     Read a list of files to be checked as zero-terminated strings
         from stdin (e.g. as written by "find -print0")

If neither any file nor option -0 or -s are specified, then this command
performs the equivalent of

  ucampas-find -print0 | ucampas-navtest -0

EOT

# parse the global uconfig.txt file
NavTree::set_global_uconfig("$RealBin/uconfig.txt");

my @fn = ();  # list of files to be checked

my $parse_options = 1;
my $filelist_read;
while (@ARGV) {
    $_ = shift @ARGV;
    if ($parse_options && /^-/) {
	if (/^-s\z/) {
	    while (defined($_ = <>)) {
		chomp;
		push @fn, $_;
	    }
	    $filelist_read = 1;
	} elsif (/^-0\z/) {
	    local $/ = "\0";
	    while (defined($_ = <>)) {
		chomp;
		push @fn, $_;
	    }
	    $filelist_read = 1;
	} elsif (/^-h/ || /^--help/) {
	    print $usage;
	    exit 0;
	} elsif (/^--\z/) {
	    $parse_options = 0;
	} else {
	    die("Unknown command line option '$_'!\n\n" . $usage);
	}
    } else {
	push @fn, $_;
    }
}

# if no file list was specified, call ucampas-find
unless (@fn || $filelist_read) {
    local $/ = "\0";
    my $find;
    open($find, "$RealBin/ucampas-find -print0 |")
	or die("Cannot execute '$RealBin/ucampas-find -print0': $!\n");
    while (defined($_ = <$find>)) {
	chomp;
	push @fn, $_;
    }
    close($find)
	or die("Cannot close '$RealBin/ucampas-find -print0': $!\n");
}

my $cur;
my $top;
my @missing = ();
foreach my $fn (@fn) {
    s/^\.\///;  # remove the redundant ./ prefix found in "find" output
    #print $fn . "\n";
    $fn = NavTree::preprocess_filename($fn, 'output');
    $cur = NavTree::find_file($fn);
    if (defined $top) {
	if ($top->cid != $cur->cid || $cur->get('unreachable')) {
	    push @missing, $fn;
	}
    } else {
	$top = $cur->top;
    }
}

if (@missing) {
    print STDERR "\nWarning: these files were not found in the Ucampas " .
	"navigation tree starting at\n" . $top->fpath . "uconfig.txt:\n\n" .
	join("\n", @missing) . "\n\nPlease update uconfig.txt appropriately.\n"
}

exit(@missing);
