Diff for /loncom/build/filecompare.pl between versions 1.8 and 1.15

version 1.8, 2001/11/17 23:00:10 version 1.15, 2014/06/09 05:14:12
Line 1 Line 1
 #!/usr/bin/perl  #!/usr/bin/perl
   
 # The LearningOnline Network with CAPA  # The LearningOnline Network with CAPA
 #  
 # filecompare.pl - script used to help probe and compare file statistics  # filecompare.pl - script used to help probe and compare file statistics
 #  #
   # $Id$
   #
   # Copyright Michigan State University Board of Trustees
   #
   # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   #
   # LON-CAPA is free software; you can redistribute it and/or modify
   # it under the terms of the GNU General Public License as published by
   # the Free Software Foundation; either version 2 of the License, or
   # (at your option) any later version.
   #
   # LON-CAPA is distributed in the hope that it will be useful,
   # but WITHOUT ANY WARRANTY; without even the implied warranty of
   # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   # GNU General Public License for more details.
   #
   # You should have received a copy of the GNU General Public License
   # along with LON-CAPA; if not, write to the Free Software
   # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   #
   # /home/httpd/html/adm/gpl.txt
   #
   # http://www.lon-capa.org/
   #
 # YEAR=2001  # YEAR=2001
 # 9/27, 10/24, 10/25, 11/4 Scott Harrison  # 9/27, 10/24, 10/25, 11/4 Scott Harrison
 # 11/14 Guy Albertelli  # 11/14 Guy Albertelli
 # 11/16,11/17 Scott Harrison  # 11/16,11/17 Scott Harrison
   # 12/3,12/5 Scott Harrison
 #  #
 # $Id$  
 ###  ###
   
 ###############################################################################  ###############################################################################
Line 34  my $invocation=<<END; Line 57  my $invocation=<<END;
 filecompare.pl [ options ... ] [FILE1] [FILE2] [ restrictions ... ]  filecompare.pl [ options ... ] [FILE1] [FILE2] [ restrictions ... ]
 or  or
 filecompare.pl [ options ... ] [DIR1] [DIR2] [ restrictions ... ]  filecompare.pl [ options ... ] [DIR1] [DIR2] [ restrictions ... ]
   or
   filecompare.pl [ options ... ] -s TARGET=[target] SOURCE=[source] MODE=[mode]
       LOC1 LOC2
   
 Restrictions: a list of space separated values (after the file/dir names)  Restrictions: a list of space separated values (after the file/dir names)
 can restrict the comparison.  can restrict the comparison.
Line 46  Options (before file/dir names): Line 72  Options (before file/dir names):
 -a show all files (with comparisons)  -a show all files (with comparisons)
 -q only show file names (based on first file/dir)  -q only show file names (based on first file/dir)
 -v verbose mode (default)  -v verbose mode (default)
 -bN buildmode (controls exit code of this script; 0 unless...)  -bN buildmode (controls EXIT code of this script; 0 unless...)
    N=1: md5sum=same --> 1; cvstime<0 --> 2     N=1: md5sum=same --> 1; cvstime<0 --> 2
    N=2: same as N=1 except without md5sum     N=2: same as N=1 except without md5sum
    N=3: md5sum=same --> 1; age<0 --> 2     N=3: md5sum=same --> 1; age<0 --> 2
    N=4: cvstime>0 --> 2     N=4: cvstime>0 --> 2
      N=5: md5sum=same --> 1; cvstime<0 and sha1sum from dns_checksums=different --> 2;
      N=6: md5sum=same --> 1; age<0 and sha1sum from dns_checksums=different --> 2;   
   
   The third way to pass arguments is set by the -s flag.
   filecompare.pl -s SOURCE=[source] TARGET=[target] MODE=[mode] LOC1 LOC2
   
   TARGET corresponds to the root path of LOC2.  SOURCE corresponds to
   the root path of LOC1.  MODE can either be file, directory, link, or fileglob.
   
 END  END
 unless (@ARGV) {  unless (@ARGV) {
     print $invocation;      print $invocation;
Line 70  unless (@ARGV) { Line 105  unless (@ARGV) {
 #   size similarity (bytes)  #   size similarity (bytes)
 #   line count difference  #   line count difference
 #   number of different lines  #   number of different lines
   #   sha1sum similarity to checksum for same file in installed version
 #  #
 # Quantities of comparison:  # Quantities of comparison:
 #   existence (no,yes); other values become 'n/a'  #   existence (no,yes); other values become 'n/a'
Line 79  unless (@ARGV) { Line 115  unless (@ARGV) {
 #   size similarity (byte difference)  #   size similarity (byte difference)
 #   line count difference (integer)  #   line count difference (integer)
 #   number of different lines (integer)  #   number of different lines (integer)
   #   sha1sum ("same" or "different") 
   
 # ---------------------------------------------------------------- Dependencies  # ---------------------------------------------------------------- Dependencies
 # implementing from unix command line (assuming bash)  # implementing from unix command line (assuming bash)
 # md5sum, diff, wc -l  # md5sum, diff, wc -l, sha1sum
   
 # ---------------------------------------------- Process command line arguments  # ---------------------------------------------- Process command line arguments
 # Flags (before file/dir names):  # Flags (before file/dir names):
Line 92  unless (@ARGV) { Line 129  unless (@ARGV) {
 # -q only show file names (based on first file/dir)  # -q only show file names (based on first file/dir)
 # -v verbose mode (default)  # -v verbose mode (default)
 # -bN build/install mode (returns exitcode)  # -bN build/install mode (returns exitcode)
   # -s status checking mode for lpml
   
 my $verbose='1';  my $verbose='1';
 my $show='all';  my $show='all';
 my $buildmode=0;  my $buildmode=0;
   my $statusmode=0;
 ALOOP: while (@ARGV) {  ALOOP: while (@ARGV) {
     my $flag;      my $flag;
     if ($ARGV[0]=~/^\-(\w)/) {      if ($ARGV[0]=~/^\-(\w)/) {
Line 112  ALOOP: while (@ARGV) { Line 152  ALOOP: while (@ARGV) {
   $show='same', last SWITCH if $flag eq 'p';    $show='same', last SWITCH if $flag eq 'p';
   $show='different', last SWITCH if $flag eq 'n';    $show='different', last SWITCH if $flag eq 'n';
   $show='all', last SWITCH if $flag eq 'a';    $show='all', last SWITCH if $flag eq 'a';
     $statusmode=1, last SWITCH if $flag eq 's';
   print($invocation), exit(1);    print($invocation), exit(1);
       }        }
     }      }
Line 122  ALOOP: while (@ARGV) { Line 163  ALOOP: while (@ARGV) {
 dowarn('Verbose: '.$verbose."\n");  dowarn('Verbose: '.$verbose."\n");
 dowarn('Show: '.$show."\n");  dowarn('Show: '.$show."\n");
   
   my @files;
   my $loc1;
   my $loc2;
   my $dirmode='directories';
   # ----------------------------------------- If status checking mode for lpml
   my ($sourceroot,$targetroot,$mode,$sourceglob,$targetglob);
   my ($source,$target);
   if ($statusmode==1) {
       ($sourceroot,$targetroot,$mode,$sourceglob,$targetglob)=splice(@ARGV,0,5);
       $targetroot.='/' if $targetroot!~/\/$/;
       $sourceroot=~s/^SOURCE\=//;
       $targetroot=~s/^TARGET\=//;
       $source=$sourceroot.'/'.$sourceglob;
       $target=$targetroot.''.$targetglob;
   #    print "SOURCE: $source\n";
   #    print "TARGET: $target\n";
       if ($mode eq 'MODE=fileglob') {
    $loc1=$source;$loc1=~s/\/[^\/]*$// if length($loc1)>2;
    $loc2=$target;$loc2=~s/\/[^\/]*$// if length($loc2)>2;
    @files=map {s/^$loc1\///;$_} glob($source);
    $dirmode='directories';
       }
       elsif ($mode eq 'MODE=file') {
    $loc1=$source;
    $loc2=$target;
    $dirmode='files';
    @files=($loc1);
       }
   }
   else {
   
 # ----------------------------------------- Process file/dir location arguments  # ----------------------------------------- Process file/dir location arguments
 # FILE1 FILE2 or DIR1 DIR2  # FILE1 FILE2 or DIR1 DIR2
 my $loc1=shift @ARGV;  $loc1=shift @ARGV;
 my $loc2=shift @ARGV;  $loc2=shift @ARGV;
 my $dirmode='directories';  
 my @files;  
 unless ($loc1 and $loc2) {  unless ($loc1 and $loc2) {
       print "LOC1: $loc1\nLOC2: $loc2\n";
     print($invocation), exit(1);      print($invocation), exit(1);
 }  }
 if (-f $loc1) {  if (-f $loc1) {
Line 147  else { Line 218  else {
 dowarn('Processing for mode: '.$dirmode."\n");  dowarn('Processing for mode: '.$dirmode."\n");
 dowarn('Location #1: '.$loc1."\n");  dowarn('Location #1: '.$loc1."\n");
 dowarn('Location #2: '.$loc2."\n");  dowarn('Location #2: '.$loc2."\n");
   }
 # --------------------------------------------- Process comparison restrictions  # --------------------------------------------- Process comparison restrictions
 # A list of space separated values (after the file/dir names)  # A list of space separated values (after the file/dir names)
 # can restrict the comparison.  # can restrict the comparison.
Line 173  my %OUTPUT=( Line 244  my %OUTPUT=(
          'size'=>(sub {print 'size: '.@_[0];return;}),           'size'=>(sub {print 'size: '.@_[0];return;}),
          'lines'=>(sub {print 'lines: '.@_[0];return;}),           'lines'=>(sub {print 'lines: '.@_[0];return;}),
          'diffs'=>(sub {print 'diffs: '.@_[0];return;}),           'diffs'=>(sub {print 'diffs: '.@_[0];return;}),
            'sha1sum'=>(sub {print 'sha1sum: '.@_[0];return;}),
 );  );
   
 my %MEASURE=(  my %MEASURE=(
Line 202  my %MEASURE=( Line 274  my %MEASURE=(
  my $rv2=`wc -l $file2`; chop $rv2;   my $rv2=`wc -l $file2`; chop $rv2;
  return ($rv1,$rv2); } ),   return ($rv1,$rv2); } ),
          'diffs'=>( sub { my ($file1,$file2)=@_;           'diffs'=>( sub { my ($file1,$file2)=@_;
    return (0,0);
  my $rv1=`diff $file1 $file2 | grep '^<' | wc -l`;   my $rv1=`diff $file1 $file2 | grep '^<' | wc -l`;
  chop $rv1; $rv1=~s/^\s+//; $rv1=~s/\s+$//;   chop $rv1; $rv1=~s/^\s+//; $rv1=~s/\s+$//;
  my $rv2=`diff $file1 $file2 | grep '^>' | wc -l`;   my $rv2=`diff $file1 $file2 | grep '^>' | wc -l`;
  chop $rv2; $rv2=~s/^\s+//; $rv2=~s/\s+$//;   chop $rv2; $rv2=~s/^\s+//; $rv2=~s/\s+$//;
  return ($rv1,$rv2); } ),   return ($rv1,$rv2); } ),
            'sha1sum'=>( sub { my ($file1,$file2)=@_;
                             if (open(my $fh,"</etc/loncapa-release.prev")) {
                                 my $loncaparev = <$fh>;
                                 close($fh);
                                 chomp($loncaparev);
                                 $loncaparev =~ s/^\QLON-CAPA release \E//;
                                 $loncaparev =~ s/\-\d{8}$//;
                                 my ($rv1)=split(/ /,`sha1sum $file2`); chomp $rv1;
                                 my $checksum;
                                 if ($loncaparev eq 'CVS_HEAD') {
                                     return ($rv1,$checksum);
                                 }
                                 elsif (open(my $fh,"<../../loncom/dns_checksums/$loncaparev.tab")) {
                                     while (<$fh>) {
                                         chomp();
                                         if (/^\Q$file2\E,[\d\.]+,(\w+)$/) {
                                             $checksum = $1;
                                             last;
                                         }
                                     }
                                     close($fh);
                                     return ($rv1,$checksum);
                                 }
                             }
                             return('n/a','n/a'); }),
 );  );
   
 FLOOP: foreach my $file (@files) {  FLOOP: foreach my $file (@files) {
Line 222  FLOOP: foreach my $file (@files) { Line 320  FLOOP: foreach my $file (@files) {
     }      }
     my ($existence1,$existence2)=&{$MEASURE{'existence'}}($file1,$file2);      my ($existence1,$existence2)=&{$MEASURE{'existence'}}($file1,$file2);
     my $existence=$existence1.':'.$existence2;      my $existence=$existence1.':'.$existence2;
     my ($cvstime,$md5sum,$age,$size,$lines,$diffs);      my ($cvstime,$md5sum,$age,$size,$lines,$diffs,$sha1sum);
     if ($existence1 eq 'no' or $existence2 eq 'no') {      if ($existence1 eq 'no' or $existence2 eq 'no') {
         $md5sum='n/a';          $md5sum='n/a';
         $age='n/a';          $age='n/a';
Line 230  FLOOP: foreach my $file (@files) { Line 328  FLOOP: foreach my $file (@files) {
         $size='n/a';          $size='n/a';
         $lines='n/a';          $lines='n/a';
         $diffs='n/a';          $diffs='n/a';
           $sha1sum='n/a';
     }      }
     else {      else {
  if ($buildmode) {   if ($buildmode) {
     my ($cvstime1,$cvstime2)=&{$MEASURE{'cvstime'}}($file1,$file2);      my ($cvstime1,$cvstime2)=&{$MEASURE{'cvstime'}}($file1,$file2);
     $cvstime=$cvstime1-$cvstime2;      $cvstime=$cvstime1-$cvstime2;
  }              my ($sha1sumfile,$checksum) = &{$MEASURE{'sha1sum'}}($file1,$file2); 
               $sha1sum='n/a';
               unless ($checksum eq 'n/a') {
                   if ($sha1sumfile && $checksum) { 
                       if ($sha1sumfile eq $checksum) {
                           $sha1sum='same';
                       }
                       else {
                           $sha1sum='different';
                       }
                   }
       }
           }
  else {   else {
     $cvstime='n/a';      $cvstime='n/a';
               $sha1sum='n/a';
  }   }
         my ($age1,$age2)=&{$MEASURE{'age'}}($file1,$file2);          my ($age1,$age2)=&{$MEASURE{'age'}}($file1,$file2);
         $age=$age1-$age2;          $age=$age1-$age2;
Line 356  FLOOP: foreach my $file (@files) { Line 468  FLOOP: foreach my $file (@files) {
     $showflag=1;      $showflag=1;
  }   }
     }      }
     if ($buildmode==1) {      if ($buildmode==1) { # -b1
         if ($md5sum eq 'same') {          if ($md5sum eq 'same') {
     exit(1);      exit(1);
  }   }
Line 367  FLOOP: foreach my $file (@files) { Line 479  FLOOP: foreach my $file (@files) {
     exit(0);      exit(0);
  }   }
     }      }
     elsif ($buildmode==2) {      elsif ($buildmode==2) { # -b2
         if ($cvstime<0) {          if ($cvstime<0) {
     exit(2);      exit(2);
  }   }
Line 375  FLOOP: foreach my $file (@files) { Line 487  FLOOP: foreach my $file (@files) {
     exit(0);      exit(0);
  }   }
     }      }
     elsif ($buildmode==3) {      elsif ($buildmode==3) { # -b3
         if ($md5sum eq 'same') {          if ($md5sum eq 'same') {
     exit(1);      exit(1);
  }   }
Line 386  FLOOP: foreach my $file (@files) { Line 498  FLOOP: foreach my $file (@files) {
     exit(0);      exit(0);
  }   }
     }      }
     elsif ($buildmode==4) {      elsif ($buildmode==4) { # -b4
  if ($existence=~/no$/) {   if ($existence=~/no$/) {
     exit(3);      exit(3);
  }   }
Line 400  FLOOP: foreach my $file (@files) { Line 512  FLOOP: foreach my $file (@files) {
     exit(0);      exit(0);
  }   }
     }      }
       elsif ($buildmode==5) { # -b5
           if ($md5sum eq 'same') {
               exit(1);
           }
           elsif ($cvstime<0) {
               if ($sha1sum eq 'same') {
                   exit(0);
               }
               else {
                   exit(2);
               }
           }
           else {
               exit(0);
           }
       }
       elsif ($buildmode==6) { # -b6
           if ($md5sum eq 'same') {
               exit(1);
           }
           elsif ($age<0) {
               if ($sha1sum eq 'same') {
                   exit(0);
               }
               else {
                   exit(2);
               }
           }
           else {
               exit(0);
           }
       }
   
     if ($showflag) {      if ($showflag) {
  print "$file";   print "$file";
  if ($verbose==1) {   if ($verbose==1) {
Line 411  FLOOP: foreach my $file (@files) { Line 556  FLOOP: foreach my $file (@files) {
     print &{$OUTPUT{'age'}}($age);      print &{$OUTPUT{'age'}}($age);
     print "\t";      print "\t";
     print &{$OUTPUT{'md5sum'}}($md5sum);      print &{$OUTPUT{'md5sum'}}($md5sum);
               print "\t";
               print &{$OUTPUT{'sha1sum'}}($sha1sum);
     print "\t";      print "\t";
     print &{$OUTPUT{'size'}}($size);      print &{$OUTPUT{'size'}}($size);
     print "\t";      print "\t";
     print &{$OUTPUT{'lines'}}($lines);      print &{$OUTPUT{'lines'}}($lines);
     print "\t";      print "\t";
     print &{$OUTPUT{'diffs'}}($diffs);      print &{$OUTPUT{'diffs'}}($diffs);
               
  }   }
  print "\n";   print "\n";
     }      }
Line 436  sub cvstime { Line 584  sub cvstime {
     }      }
     my $cvstime;      my $cvstime;
     if ($buildmode!=3) {      if ($buildmode!=3) {
  my $entry=`grep '^/$file/' ${path}CVS/Entries` or   my $entry=`grep '^/$file/' ${path}CVS/Entries 2>/dev/null`;
     die('*** ERROR *** cannot grep against '.${path}.  # or
  'CVS/Entries for ' .$file . "\n");  #    die('*** WARNING *** cannot grep against '.${path}.
         my @fields=split(/\//,$entry);  # 'CVS/Entries for ' .$file . "\n");
         $cvstime=`date -d '$fields[3] UTC' --utc +"%s"`;   if ($entry) {
         chomp $cvstime;      my @fields=split(/\//,$entry);
       $cvstime=`date -d '$fields[3] UTC' --utc +"%s"`;
       chomp $cvstime;
    }
    else {
       $cvstime='n/a';
    }
     }      }
     else {      else {
  $cvstime='n/a';   $cvstime='n/a';

Removed from v.1.8  
changed lines
  Added in v.1.15


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>