#!/usr/bin/perl -w
# If the above path is incorrect for your system,
# FOLLOW THE INSTALLATION INSTRUCTIONS in README.

#
# mkall
# $Id: mkall,v 1.18 2007/02/23 05:14:59 johnh Exp $
#
# Copyright (C) 1996,2012  Free Software Foundation, Inc.
# Comments to <johnh@isi.edu>.
#
# This file is under the Gnu Public License, version 2.
# For details see the COPYING which accompanies this distribution.
#

sub usage {
    print STDOUT <<END;
usage: $0

Does all reindexing needed for notes-mode.
END
    exit 1;
}


require 5.000;
BEGIN { unshift(@INC, $ENV{'NOTES_BIN_DIR'}); };
use NotesVars;
use strict;
use Config;

&usage if (($#ARGV >= 0 && $ARGV[0] eq '-?'));

my($perl) = &find_perl_binary;

# xxx: currently rawindex generates @subjects that index uses.
# Should remove this dependency.
my(@subjects) = ();

&make_rawindex;
&make_index;
&make_index_cache;
&make_prevnext;
&make_mknew_cache;
&fix_perms;

exit 0;


sub find_perl_binary {
    my($perl) = $^X;
    return $perl if (-x $perl);
    $perl = $Config{'installbin'} . "/perl";
    return $perl if (-x $perl);
    # If we can't find perl, then we assume the user's set the #! lines correctly.
    return '';
}


sub run_over_all_notes {
    my($cmd, $user_cmd_name) = @_;
    open(CMD, "| $cmd") || die ("$0: cannot run $user_cmd_name.\n");
    foreach (glob "$::notes{'int_glob'}/$::notes{'file_glob'}") {
	print CMD "$_\n";
    };    
    close CMD;
    if ($? >> 8) {
        die "$0: $user_cmd_name failed.";
    };
}


#
# rawindex 
#
#
# The main thing that happens here is we find and sort the notes entries.
# We do the sorting in perl because the system sort is less portable
# (wrt stability, for example).
#
sub make_rawindex {
    chdir ($::notes{'dir'}) || die "$0: cannot cd to $::notes{'dir'}.\n";
    # if (-f "rawindex") {
    #     rename('rawindex', 'rawindex~') || die "$0: cannot rename rawindex.\n";
    # };
    # my($sed_arg) = '"s@' . $::notes{home} . '@/~@"';
    # system(<<END);
    #     $::notes{'bin_dir'}/mkrawindex $::notes{'dir'}/$::notes{'int_glob'}/$::notes{'file_glob'} |
    #     sort -f -t# +1 +0 |
    #     sed $sed_arg > rawindex
    # END
    # if ($? >> 8) {
    #     rename('rawindex', 'rawindex.bad');
    #     rename('rawindex~', 'rawindex');
    #     die "$0: rawindex pipeline failed.";
    # };
    #
    # xxx: eventually this will overflow the buffer and we'll need to
    # do something like xargs.  However, in 10 years of use this hasn't happened
    # for me yet.
    run_over_all_notes("$perl $::notes{'bin_dir'}/mkrawindex -X >prerawindex", "mkrawindex");
#    open (IF, "$perl $::notes{'bin_dir'}/mkrawindex $::notes{'dir'}/$::notes{'int_glob'}/$::notes{'file_glob'} |") || die "$0: cannot run mkrawindex\n";
#    binmode IF;
    open(IF, "<prerawindex") || die  "$0: cannot open prerawindex.\n";
    binmode IF;
    open (OF, ">rawindex+") || die "$0: cannot write to rawindex+\n";
    binmode OF;
    my($internal_marker) = chr(1);
    foreach (<IF>) {
        chomp;
	s@$::notes{'home'}@/~@;
	my($left, $right) = /^([^#]+)\#(.*)$/;
	push(@subjects, "${right}${internal_marker}${left}");
    };
    close IF;
    @subjects = sort { uc($a) cmp uc($b) } @subjects;
    foreach (0..$#subjects) {
        my($left, $right) = ($subjects[$_] =~ /^(.+)${internal_marker}(.*)$/);
	$subjects[$_] = "$right#$left";
	print OF "$subjects[$_]\n";
    };
    close OF;
    if (-f 'rawindex') {
        rename('rawindex', 'rawindex~') || die "$0: rename rawindex{,~} failed.\n";
    };
    rename('rawindex+', 'rawindex') || die "$0: rename rawindex{+,} failed.\n";
}

#
# index
#
sub make_index {
    if (-f 'index') {
        rename('index', 'index~') || die "$0: rename index{,~} failed.\n";
    };
    open (OF, "| $perl $::notes{'bin_dir'}/mkindex > index") || die "$0: cannot run mkindex.\n";
    binmode OF;
    my($last);
    foreach (@subjects) {
        if (!defined($last) || $last ne uc($_)) {
	    print OF "$_\n";
	    $last = uc($_);
         };
    };
    close OF;
    if ($? >> 8) {
        rename('index', 'index.bad') || warn "$0: recovery rename index{,.bad} failed.\n";
	rename('index~', 'index') || warn "$0: recovery rename index{~,} failed.\n";
	die "$0: index pipeline failed.";
    };
}

#
# index_cache.el
#
# Yes, the code should probably be compiled,
# but compilation time doesn't seem to be the problem.
#
sub make_index_cache {
    if (-f 'index_cache.el') {
        rename('index_cache.el', 'index_cache.el~') || die "$0: rename index_cache.el{,~} failed.\n";
    };
    system(<<END);
    $perl $::notes{'bin_dir'}/mkindexcache < index > index_cache.el
END
    #    emacs -batch --eval '(byte-compile-file "index_cache.el")' 2>&1 | grep -v 'free variable'
    if ($? >> 8) {
        rename('index_cache.el', 'index_cache.el.bad') || warn "$0: reanme index_cache.el{,.bad} failed.\n";
	rename('index_cache.el~', 'index_cache.el') || warn "$0: rename index_cache.el{~,} failed.\n";
	unlink('index_cache.elc') if (-f 'index_cache.elc');
	die "$0: index pipeline failed.";
    };
    #
    # Bug found by Klaus Zeitler <kzeitler@lucent.com>:
    # if we generate index_cache.el in less than a second,
    # it won't be considered up-to-date.
    #
    if (-M 'index' == -M 'index_cache.el') {
	# We're too fast---stall and update the file
	sleep(1);   # stall
	system('touch index_cache.el');   # "update"
    };
}


#
# prevnext
#
sub make_prevnext {
    run_over_all_notes("$perl $::notes{'bin_dir'}/mkprevnext -X ./rawindex", "mkprevnext");
}

#
# mknew cache
#
sub make_mknew_cache {
    my($todays_file) = &epoch_to_pathname(time);
    system(<<END);
    $perl $::notes{'bin_dir'}/mknew -c $todays_file >./mknew.cache
END
}

#
# fix permissions
#
sub fix_perms {
    my($perm);
    foreach (glob("*"), glob("*/*")) {
	my($mode) = (stat($_))[2];
	if ($mode & 0077) {
	    chmod (($mode & 0700), $_) || warn "$0: could not chmod $_.\n";
        };
    };
}


