#!/usr/local/bin/perl
#
# Copyright (c) 1998-2024 Luke Mewburn <luke@mewburn.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:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. 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.
# 3. The name of the author may not be used to endorse or promote products
#    derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
#
# genmodules --
#	update cvs modules file
#
#	checks commitlogs for valid entries, and all entries in
#	current log after a line of the form:
#		'# Do not edit below here'
#

require "dumpvar.pl";

$| = 1;
die("CVSROOT not set - exiting\n") unless ($ENV{"CVSROOT"});
$root = $ENV{"CVSROOT"};
$root =~ s#/?$##;

$tmpdir = "modules.$$";
chdir("/tmp") || die("can't change to /tmp - $!\n");
print "trying to checkout modules to /tmp/$tmpdir\n";
system("cvs -l checkout -d $tmpdir CVSROOT/modules");
if (($? >> 8) != 0) {
	die("'cvs -l checkout -d $tmpdir modules' returned $!\n");
}
chdir($tmpdir) || die("can't change to $tmpdir - $!\n");

print "reading old modules file\n";
open(MF, "$root/CVSROOT/modules") || die("can't open CVSROOT/modules - $!\n");
open(TMP, "> modules") || die("can't write to modules - $!\n");
while (<MF>) {
	if (1 .. /^# Do not edit below here/) {
		print TMP;
		next;
	}
	chop;
	s/\s*#.*//;
	next if /^$/;
	($name, $dir) = split;
	unless (-d "$root/$dir") {
		if ($dir_warned{$dir}) {
			next;
		}
		$dir_warned{$dir}++;
		warn "non-existant dir: $dir\n";
		next;
	}
	if ($n_to_d{$name}) {
		unless ($module_warned{$name}) {
			warn "line $. module exists: $name\n";
		}
		$module_warned{$name}++;
	}
	$d_to_n{$dir} = $name;
	$n_to_d{$name} = $dir;
}
close(MF);


$logs = $root . "/CVSROOT/commitlog*";
@ARGV = <${logs}>;

print "parsing commit logs\n";
LOGLOOP:
while (<>) {
	chop;
	next unless m#^Update of $root/(.*)#;
	$dir = $1;
	unless (-d "$root/$dir")
	{
		if ($dir_warned{$dir}) {
			next;
		}
		$dir_warned{$dir}++;
		warn "non-existant dir: $dir\n";
		next;
	}
	if ($d_to_n{$dir}) {
		next;
	}
	@elm = split(/\//, $dir);
	$name = @elm[@elm - 1];
	if ($n_to_d{$name}) {
		unless ($module_warned{$name}) {
			warn "module exists: $name\n";
		}
		$module_warned{$name}++;
	}
	$cur = "";
	while ($x = shift(@elm)) {
		$cur .= "/" if ($cur);
		$cur .= "$x";
		if ($d_to_n{$cur} && scalar(@elm)) {
			next LOGLOOP;
		}
	}
	$d_to_n{$dir} = $name;
	$n_to_d{$name} = $dir;
}

delete $n_to_d{"CVSROOT"};
delete $d_to_n{"CVSROOT"};

foreach $x (sort keys %n_to_d) {
	printf(TMP "%-16s %s\n", $x, $n_to_d{$x});
}
close(TMP);

#
# xxx: slurp in output and make the commit message the differences
#
print "differences:\n";
system("cvs diff modules");
print "\n";

print "trying to commit\n";
system("cvs commit -m 'modules update'");
if (($? >> 8) != 0) {
	warn("cvs commit returned $!\n");
}

print "removing tmp dir\n";
chdir("/tmp") || die("can't change to /tmp - $!\n");
system("rm -rf $tmpdir");
if (($? >> 8) != 0) {
	warn("rm -rf $tmpdir returned $!\n");
}
