#!/afs/athena/contrib/perl/perl5
#
# Replaces http://fishwrap.mit.edu with http://hacks.mit.edu 
# in a tree of files without changing file modification time.
#
# Usage:  copyacls.pl basedir
#

use File::Find;

$File::Find::dont_use_nlink = 1;

$basedir;

sub rcs_status {
    # effects: tests whether a file is under RCS control.
    #          Returns "locked" if a lock is held by someone.
    #          Returns "unlocked" if no locks are held.
    #          Returns "norcs" if the file isn't under RCS control.
    my ($file) = @_;
    my $hitlocksline=0; my $islocked=0; my $norcs=1;

    open RLOG, "rlog $file|" || do { print "*** rcs_status: $file not under RCS control\n"; return "norcs"; };
    foreach (<RLOG>) {
	if (/^RCS file: /) { $norcs=0; }
	if ( $hitlocksline ) {
	    if (!/^access list:/) {
		/^\s+(\S+):\s/;
		print "*** rcs_status: $file locked by $1\n";
		$islocked=1;
	    }
	    $hitlocksline = 0;
	} elsif (/^locks: /) {
	    $hitlocksline=1; 
	}	
    }
    close RLOG;
    if ($norcs) {
	print "*** rcs_status: $file not under RCS control\n";
	return "norcs"; 
    }
    if (!$islocked) {	       
	my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, 
	    $atime, $mtime, $ctime, $blksize, $blocks) = stat $file;
	if ($mode & 0222) {
	    print "*** rcs_status: $file is unlocked but writeable\n";
	    return "locked";  # might as well be...
	}
    }
    return ($islocked?"locked":"unlocked");
}

sub contains_fishwrap {
    # checks whether a file contains the string we care about...
    my ($file) = @_;
    my $containsfw = 0;
    open FIN, "<$file" or do { 
	print "*** contains_fishwrap: couldn't open $file\n"; 
	return 0;
    };
    foreach $curline (<FIN>) {
	$containsfw=1 if (($curline =~ m|http://fishwrap.mit.edu/Hacks|)
			  || ($curline =~ m|cgiecho/afs/fishwrap.mit.edu/Hacks/Gallery/misc|)
			  || ($curline =~ m|cgiemail/afs/fishwrap.mit.edu/Hacks/Gallery/misc|));

	$curline =~ s|http://fishwrap.mit.edu/Hacks||g;
	if ($curline =~ m|fishwrap.mit.edu/afs|) {
	    print "*** found fishwrap.mit.edu/afs reference in $file\n";
	} 
	if ($curline =~ m|/afs/fishwrap.mit.edu|) {
	    print "*** found /afs/fishwrap.mit.edu reference in $file\n";
	} 
	if ($curline =~ m|http://fishwrap.mit.edu|) {
	    print "*** found http://fishwrap.mit.edu reference in $file\n";
	} 
    }    
    close FIN;
    return $containsfw;
}

sub do_replace {
    # does the actual replacement.  
    # gets an RCS lock if necessary then checks back in when done...

    my ($file) = @_;

    if (!contains_fishwrap($file)) {
	print "do_replace: $file doesn't contain the string\n";
	return 1;
    }

    $rcsstat = rcs_status $file;
    if ($rcsstat eq "locked") {
	return 0;
    } elsif ($rcsstat eq "unlocked") {
	$co_ret = system("co -l $file");
	if ($co_ret != 0) {
	    print "*** do_replace: couldn't check out file (got $co_ret)!!!\n";
	    return 0;
	}
    }

    if (-l $file) { print "*** do_replace: passed a symlink!\n"; return 0; }
    my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, 
     $atime, $mtime, $ctime, $blksize, $blocks) = stat $file;
    $tmpfile = $file.".tmpMAGIC478935";
    rename $file, $tmpfile;
    open FIN, "<$tmpfile" or do { 
	print "*** do_replace: couldn't open $tmpfile\n"; 
	rename $tmpfile, $file; 
	return 0;
    };
    open FOUT, ">$file" or do { 
	print "*** do_replace: couldn't open output file $file\n"; 
	rename $tmpfile, $file; 
	return 0; 
    };
    foreach $curline (<FIN>) {
	$curline =~ s|http://fishwrap.mit.edu/Hacks|http://hacks.mit.edu/Hacks|g;
        $curline =~ s|cgiecho/afs/fishwrap.mit.edu/Hacks/Gallery/misc|cgiecho/afs/sipb.mit.edu/contrib/hacks/Hacks/misc|g;
        $curline =~ s|cgiemail/afs/fishwrap.mit.edu/Hacks/Gallery/misc|cgiemail/afs/sipb.mit.edu/contrib/hacks/Hacks/misc|g;

	print FOUT $curline;
    }

    close FIN; close FOUT;
    unlink $tmpfile;
    chmod $mode, $file;
    chown $uid, $gid, $file;

    if ($rcsstat eq "unlocked") {
	$ci_ret = system("ci -u -m\"changed base address to hacks.mit.edu\" $file");
	if ($co_ret != 0) {
	    print "*** do_replace: couldn't check in file (got $ci_ret)!!!\n";
	    return 0;
	}
    } else {
	utime $atime, $mtime, $file;
    }

    print "do_replace: completed changing $file\n";
    return 1;
}

sub print_usage {
    print "Usage:  $0 basedir\n";
    exit -1;
}

sub dir_action {
    #print "trying $File::Find::name\n";
    my $skipit=0;
    $skipit=1 if (! -f $_);
    $skipit=1 if (-l $_);
    $skipit=1 if (!(/\.html$/ || /\.htm$/));
    return if $skipit;
    print "\n>>>>>> changing base for $File::Find::name\n";
    my $retval = do_replace $File::Find::name;
    ($retval==0) && print "*** FAILURE: couldn't handle $File::Find::name\n";

    #my $containsfw = contains_fishwrap $File::Find::name;
    #printf "\tcontains fishwrap: %s\n", $containsfw;
    #if ($containsfw) {
    #	printf "\trcs status: %s\n", (rcs_status $File::Find::name);
    #}
}

$basedir    = $ARGV[0] || print_usage;

find (\&dir_action, $basedir);

#do_replace($basedir);

#print rcs_status $basedir;
#print "\n";
