#!/usr/bin/perl -w
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
#NAME
#  files.sh <file_list
#
#SYNOPSIS
#  files.sh < [file]..
#
#REQUIRES
#
#DESCRIPTION
# This script takes the output of a "ls -li ... | sort -n" command, and
# runs through the list looking for files with the same inode numbers
# (i.e., links to the same files).  For each such group of linked files,
# Makefile commands are produced that will ensure that they are still
# linked.  If links are broken, the first file in the group is considered
# the "authoritative" version, and the files with different inode numbers
# are relinked to it.
#
# This can be used in a web directory that's supposed to contain a list
# of files fromassorted other places in the file system.  It's easy for
# such directories' links to be "broken" by tools like rsync, wget, curl,
# and of course make itself. So at approprate times, a Makefile in the web
# directory can contain the output of this script, and a "make" command
# will make sure that the web directory's files are all properly linked.
#
#OPTIONS
#
#EXAMPLES
#  find dir.. -name '..' -exec ls -li ';' -print0 | xargs -0 files.sh >& Makefile
#
#NOTE
#  All verbose/debug lines are written to STDERR.
#  The Makefile lines are written to STDOUT.
#FILES
#
#BUGS
#  This program currently only reads stdin; I'll add file input later,
#  when I find that I want/need it. ;-)
#
#SEE ALSO
#
#AUTHOR
#  John Chambers <jc@trillian.mit.edu> 2019 (Suggestions are welcome.)
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

$| = 1;
$exitstat = 0;
$colonkludge = 1;	# Grrr .....
($P = $0) =~ s".*/"";
$V = $ENV{"V_$P"} || $ENV{"D_$P"} || 2;	# Verbose level.
print STDERR "$P " . join(', ',@ARGV) . " [V=$V]\n" if $V>1;

for $_ (<>) {
	$_ =~ s/[\r\s]*$//;
	print STDERR "LINE \"$_\" ...\n" if $V>1;
	next unless $_;
	if ($_ =~ /^#/) {
		print STDERR "$P: comment ignored.\n" if $V>2;
		next;
	} elsif (($inode,$path) = ($_ =~ /^(\d+)\s+(.*)$/)) {
		print STDERR "Orig: inode=$inode path=\"$path\"\n" if $V>1;
		if (defined $Orig{$inode}) {
			print STDERR "$P: inode=$inode not new.\n" if $V>2;
			$Link{$path} = $inode;	# This file is linked to an original
			&make($path);			# Generate the Makefile lines
		} else {
			print STDERR "$P: inode=$inode new.\n" if $V>1;
			$Orig{$inode} = $path;	# This file is an "original"
		}
	} else {
		print STDERR "Line \"$_\" not recognized.\n" if $V>1;
		next;
	}
	print STDERR "Next line ...\n\n" if $V>1;
}

if (@Makes) {	# Did we generate any Makefile entries?
	print '\ntunelist: ' . join(' ', @Makes);		# Output the list in one long line
}

print "$P: Exit with status $exitstat.\n" if $V>1;
exit $exitstat;

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
#
# Generate the Makefile lines
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
sub make {my $P = "make"; local($path) = @_;
	local($inum) = $Link{$path};
	local($orig) = $Orig{$inum};
	if ($colonkludge) {
		$path =~ s':'\\:'g;
		$orig =~ s':'\\:'g;
	}
	print "$path: $orig\n";
	print "\tln -f $orig $path\n";
	push @Makes, $path;		# Keep a list of all the files we're making
}
