#!/usr/local/bin/perl
# $Id: find.pm,v 1.9 2001/06/02 10:09:00 stephens Exp $

use ion::_cvs::entry;

#########################################################

package ion::_cvs;

#print STDERR "ion::_cvs::find\n";

use Cwd;
use File::Find;
use File::Basename;

$debug = 0;
$testing = 0;
$find::show_funny_entries = 0;
$find::all_files = 0;

sub read_CVS_Entries {
    my($dir) = @_;
    my($in);
    my($Repository);
    
    $in = "$dir/CVS/Repository";
    if ( -f $in ) {
	open($in, "<$in") || die "$in: $!";
	$Repository = <$in>;
	chop $Repository;
	close($in);
    }

    $in = "$dir/CVS/Entries";
    if ( -f $in ) {
	my(@entries);
	my($line);
	my($lineno) = 0;

	open($in, "<$in") || die "$in: $!";
	while ( $line = <$in> ) {
	    chomp $line;
	    $lineno ++;
	    
	    my($rec);

	    $rec = [ split('/', $line) ];

	    if ( $#{$rec} > 0 ) {
		$rec->[6] = $dir;
		$rec->[7] = $rec->[0] eq 'D' ? "$Repository/$rec->[1]" : "$Repository/$rec->[1],v";
		$rec->[8] = $rec->[6] . '/' . $rec->[1];

		#print join('+', $#{$rec}, @{$rec}), "\n";

	        ion::_cvs::entry::make($rec);
		
		#print join('-', $#{$rec}, @{$rec}), "\n";
		#die "$in:$lineno:$line" if ( $#{$rec} <= 0 );

		push(@entries, $rec);
	    } else {
		warn "$in:$lineno: funny entry: '$line'\n" if ( $ion::_cvs::find::show_funny_entries );
	    }
	}
	close($in);
	@entries;
    } else {
	0;
    }
}

sub do_entry {
    my($entry, $proc, $data) = @_;
    #print join('|', $#{$rec}, @{$rec}), "\n";
    &{$proc}($entry, $data);
    if ( $entry->[0] eq 'D' ) {
	my($se);
        foreach $se ( read_CVS_Entries($entry->[8]) ) {
	    &{$proc}($se, $data);
	    do_entry($se, $proc, $data);
	}
    }
}

#########################################################


sub wanted {
    print STDERR "wanted: $File::Find::name\n" if ( $debug );
    if ( $_ eq 'CVS' ) {
	$File::Find::prune = 1;
    } else {
	if ( -d && (-f "$_/CVS/Entries" || -f "../CVS/Entries") ) {
	    #print STDERR "Found dir $File::Find::name\n";
	    push(@found_files, $File::Find::name);
	    $File::Find::prune = 1;
	} elsif ( -f ) {
	    #print STDERR "Found file $File::Find::name\n";
	    push(@found_files, $File::Find::name);
	}
    }
}

sub find {
    my($proc, $data, @files) = @_;

    # Collect files under CVS control
    @found_files = ();
    my($save_cwd) = getcwd;
    File::Find::find(\&wanted, @files);
    chdir($save_cwd) || die "$save_cwd: $!";

#########################################################

#print STDERR "files = (", join("\n\t", @files), ")\n";

    my($path);
    foreach $path ( @found_files ) {
	my($dir, $file);
	my($entry);
    
	$dir = dirname($path);
	$file = basename($path);
	print STDERR "$path:$dir:$file\n" if ( $debug );

	if ( -d $path && -f "$path/CVS/Entries" ) {
	    print STDERR "$path is a dir\n" if ( $debug );
	    foreach $entry ( read_CVS_Entries($path) ) {
		do_entry($entry, $proc, $data);
	    }
	} elsif ( $file ne '.' && -f "$dir/CVS/Entries" ) {
	    #print STDERR "Search for $file in $dir/CVS\n";
	  ENTRY: foreach $entry ( read_CVS_Entries($dir) ) {
	      #print STDERR "Entry name $entry->[1]\n";
	      if ( $file eq $entry->[1] ) {
		  print STDERR "Found entry for $file in $dir/CVS\n" if ( $debug);
		  do_entry($entry, $proc, $data);
		  last ENTRY;
	      }
	  }
	}
    }
}


1;
