#! /usr/bin/perl -w

use Getopt::Std;

# This program checks that all the version numbers scattered
# throughout LVM match.  The data section at the end of this file
# contains lines which specify the locations of these version numbers.
# These specifications are of the form:
# <file>:<line>:<pattern>

# Where: 

# 'file' is the name of the file relative to the top of the LVM tree

# 'line' is the line number (numeric) or a regular expression that
#        uniquely selects the line.

# 'pattern' is a regular expression used to extract the version number
#        from the line.  After this pattern has run $1 (ie, the expression
#        contained within the first set of brackets) should contain the
#        version number.

# Run this program from the root of the LVM tree, an optional argument
# tells it what version number should be present.  If this argument
# isn't present it lists all version numbers;  The argument is specified
# with the '-t' flag

# You can also do a search and replace on targets using the combination of
# the '-t', '-s', and '-d' flags.  Specify the target of your search with '-t'
# the destination of your search with '-d', and the fact that you want to
# search with '-s'.  By default, the seach-and-replace feature backs up all
# files it touches to $file.$TIMESTAMP.  You can shut this feature off by 
# specifying the -bn flag at the command line.

# cd ~/develop/LVM
# scripts/check_version_numbers

# scripts/check_version_numbers -t 0.9.1_beta2

# scripts/check_version_numbers -s -t 0.9.1_beta2 -d 0.9.1_beta3

$err = getopts('b:t:d:hs');
if($err == 0) {
  $opt_h = 1;
}

$name = $0;
$name =~ s/(.*\/)(.*)/$2/;

# Hurrah for complex command line flag dependancies!
if(defined($opt_t)) {
  $target = $opt_t;
  if(defined($opt_s)) {
    if(defined($opt_d)) {
      $destination = $opt_d;
    }
    else {
      $opt_h = 1;
    }
  }
  else {
    if(defined($opt_d)) {
      $opt_h = 1;
    }
  }
}

if(defined($opt_h)) {
  die "usage: $name [-h -t Target [-s -d Destination -b n]]\n\t-h\tthis help message\n\t-t\tVersion string we're looking for\n\t-s\tSearch-and-replace: Destination for Target\n\t-d\tChange target to destination if -s flag is given\n\t-b\tBackup modified files? (default: y)\n";
}

# default is to backup all files with a time and date stamp
if(!defined($opt_b)) {
  $opt_b = "y";
}

$ret = 0;
# scan through the regexps at the bottom of the file
while(<DATA>) {
    chomp;
    next if(m/^\s*$/);

    ($file, $line, $pattern) = split(':', $_);

    if(!defined($file) || !defined($line) || !defined($pattern)) {
	print "Malformed line: '$_'\n";
	next;
    }

    # if we're doing a target destination substitution...
    if(defined($opt_s)) {
       # do a backup unless explicitly requested not to
       if($opt_b ne "n") {
         local ($sec,$min,$hour,$mday,$mon,$year) = localtime(time());
         local $thisdate = "$mday$mon$year\_$hour\:$min\.$sec";
         system "cp $file $file.$thisdate";
       }
       # open a temporary output file
       open(OUT, ">$file.tmp") or die("couldn't open '$file.tmp'\n");
    }
    open(IN, "$file") or die("couldn't open '$file'\n");
    
    $match = 0;
    $count = 0;
    $number = ($line =~ /^[0-9]+$/) ? 1 : 0;


    while(!$match && ($in = <IN>)) {
	chomp $in;
	$count++;
	if($number) {
	    if($count == $line) {$match = 1;}
	    else {
              if(defined($opt_s)) {print IN "$in\n";}
            }
	} else {
	    if($in =~ m/$line/) {$match = 1;}
	    else {
	       if(defined($opt_s)) {print OUT "$in\n";}
	    }
	}
    }
    if(!$match) {
	print STDOUT "Couldn't find line matching $file:$line\n";
    } else {
        # if we're doing a search and replace
        if(defined($opt_s)) {
	   local $orig_line = $in;
	   # put the modified line in if we find the search target
           if($in =~ s/$target/$destination/) {
	     print OUT "$in\n";
	   }
	   # otherwise put in the unmodified line
	   else {
	     print OUT "$orig_line\n";
	   }
	}
	else {
	if($in =~ m/$pattern/) {
	    if(defined($target)) {
		if(!($1 eq $target)) {
		    print "$file:$count:$1\n";
		    $ret = 1;
		}
	    } else {
		print "$file:$count:$1\n";
	    }
	} else {
	    print "couldn't match pattern on $file:$line:$pattern\n";
	}
      }
    }
    # we handle cleanup differently for the search-and-replace option
    if(defined($opt_s)){
      if($match) {
        while(($in = <IN>)) {
          chomp $in;
          print OUT "$in\n";
        }
        system "cp $file.tmp $file;";
      }
      close(OUT);
      system "rm $file.tmp";
    }
    close(IN);
}

exit($ret);

__DATA__
README:1:LVM\s+(\S+)
README:This directory contains:version\s+(\S+)\s+release
README:\.tar\.gz:lvm_(.+)\.tar\.gz

INSTALL:1:LVM\s+(\S+)
INSTALL:1. Change to:\/([^\/]+)
INSTALL:6. Change back to :LVM\/([^\/]+)
INSTALL:1. change directory:\/([^\/]+)

FAQ:1:LVM\s+(\S+)

KNOWN_BUGS:1:LVM\s+(\S+)
KNOWN_BUGS:Known bugs in LVM:LVM\s+(.+).\s*

LVM-HOWTO:1:LVM\s+(\S+)

TODO:1:LVM\s+(\S+)

WHATSNEW:1:LVM\s+(\S+)
WHATSNEW:What is new in LVM:LVM\s+(\S+)

tools/lvmcreate_initrd:Logical Volume Manager:er (.*) by Heinz

