hi,

attached are 2 files: a script that checks all files for the Last Changed Date according to SVN, and updates the file if its year > copyright notice in the file. I'm not very good with Perl, so it might be badly programmed... However, it only needs running once.

The 2nd file is a test, and again, this only needs to run once a year.

Issues with the test file:
* I redirect stderr to stdout, maybe it needs to be restored later, but I can imagine each test is a new invocation of perl, so in that case it's not necessary. * if it finds a file that is literally out of date (it needs copyright notice update), it will only give an error message, not the file name (which should really be the case, otherwise, you don't know what file to fix)

* on ctrl-c it won't stop (well, for 1 second after which it continues...) I guess it has to do with me using File::Find...

The test file can just be put in the parrot/t/configure directory, that one will be run first when doing make test (so you don't have to wait for it to run)

hope this helps,
klaas-jan


#! perl
# Copyright (C) 2007, The Perl Foundation.

=head1 NAME

adjustcopyright.t - check copyright for all files in the parrot distr.

=head1 SYNOPSIS



=head1 DESCRIPTION

This test checks the "Last Changed Date" according to SVN for the year
it was changed. Then it looks in the file being processed for a copyright
notice, and extracts the year. Then, if $SVNYear > $fileYear, fail test
(and the copyright should be updated).

=head1 ISSUES

=over 4

=item *

C^C won't stop the testing...

=item *

How to restore stderr after having it redirected to stdout?






=cut

use strict;
use warnings;
use lib qw( . lib ../lib ../../lib );

use File::Find;
use Parrot::Test;
use Parrot::Config;
use Test::More;


# don't know how many files will be tested:
plan tests => 1;

sub vdiag(@) { &diag if $ENV{TEST_VERBOSE} }


sub checkCopyright {
                        
                my $file = $_;
    
    # only handle files, not directories
    return unless -f $file;
    
    # only handle text files
    return unless -T $file;
            
                # if there's '.svn' in the filename, it's the directory 
(probably?)     
                return if $File::Find::name =~ m/.*\.svn.*/;
                                                                              
                my $cmd = "svn info $File::Find::name";
                
                #
                # FIXME: restore stderr->stdout after we're done.
                #
                my $output = `$cmd 2>&1`;
                
                my $SVNYear = undef;                                    # to 
store the year according to SVN    
                
    if ($output =~ m/.*Last Changed Date:\s+(\d\d\d\d).*/) {                    
                        
                        $SVNYear = $1;                  
    }
    else {
        return;
    }

    open(FILE, "< $File::Find::name") or die "cannot open file 
$File::Find::name";
       
    while(<FILE>) {
                                        
                        # on failure, it should emit the failing file's name so 
we can fix it!                                          
                                        
        # check for copyright lines containing only 1 year; note the matching 
space here.
        if ($_ =~ m/.*[cC]opyright[^[\d\d\d\d\-]]*(\d\d\d\d).*/ ) { # check for 
match
                                
                # ok found it, now compare with $SVNYear
                # only change when SVN Year > current
                is($1, $SVNYear);
        }    
        # check for copyright lines like X-Y                    
        elsif ($_ =~ m/.*[cC]opyright[^\d]*\d\d\d\d\-(\d\d\d\d).*/ ) {          
        
                is($1, $SVNYear);
        }
   } 
   
   close(FILE);
                
}
        
        
{

        # set $parrotRootDir to parrot build directory: 
        my $parrotRootDir = $PConfig{'build_dir'};
                
        # find takes an array containing directories to 
        # be processed, we only have 1 directory: parrot
        my @dirlist = ();       
        push @dirlist, $parrotRootDir;
        
        # check copyright for each file.
        find(\&checkCopyright, @dirlist);
}
#
# Start of a script to recursively process all files in a directory to change 
the copyright notice.
#
use File::Find;
use strict;
use warnings;

my @unhandled_files = ();
my @handled_files = ();

sub process_file {
                my $oldValue = 2006;            # the minimal value for a year 
to be replaced           
    
    my $shouldChange = 0;       # flag only set when file was changed in a year 
later than it's copyright notice year.
    
    my $file = $_;
    
    # only handle files, not directories
    return unless -f $file;
    
    # only handle text files
    return unless -T $file;
    
    # only handle file if it is writable
    return unless -w $file;
    
    # open file for reading and writing
    open(FILE, "+< $file") or die "can't open file $File::Find::name: $!";
            
     
    
    my $filename = $File::Find::name;
    
    
    
    unless (-e $filename) {
        die "File $filename does not exist!\n";
    } else {
        print "Handling file $filename\n";
    }
   
    print "Getting SVN info from $File::Find::name...\n";
    my $str = "svn info $filename > svninfo.txt"; 
    print "\nExecuting:\n$str";
    
    # <allison> kjs: may make sense to just use 'capture_output' from 
lib/Parrot/Configure/Step.pm
    # (instead of system)           
    system($str);                 
    open(TEMPFILE, "< svninfo.txt") or die "cannot open file svninfo.txt";
        
    my $SVNYear = undef;                                        # to store the 
year according to SVN    
    while(<TEMPFILE>) {
        
        # get the year from that line:
        if ($_ =~ m/Last Changed Date:\s+(\d\d\d\d).*/) {
                print "\nMatched: $_'\nYear: $1\n";        
                
                $SVNYear = $1;                  
        }
    }
        
    close(TEMPFILE);    
    
    
    
    unless (defined $SVNYear) {
        print "Mmmm: no 'Last Changed Date' according to SVN\nSkipping file 
$File::Find::name\n";
        push @unhandled_files, $filename;
        return;
    }
        
    
    # buffer to store file contents
    my $filebuffer = '';   
    
    # read file line by line
    while(<FILE>) {
        
        # flag indicating whether the file has been changed yet
        my $changed = 0;                                                        
                
        # check for copyright lines containing only 1 year; note the matching 
space here.
        if ($_ =~ m/.*[cC]opyright[^[\d\d\d\d\-]]*(\d\d\d\d).*/ ) { # check for 
match
                 
                print "Found copyright notice with year $1\n";
                # ok found it, now compare with $SVNYear
                # only change when SVN Year > current
                if ($SVNYear > $1) {
                                    
                        print "CASE 1\n";                       
                        print "Ok, the 'Last Changed Date' according to SVN is: 
$SVNYear.\n";
                        print "This is a later date than the current copyright 
notice date, which is $1.\n";
                        print "I'll change\n\t'$_'\n\tinto: ";
                        
                        # change a notice like '2006' into '2006-2007'
                        $_ =~ s/$1/$1\-$SVNYear/;
                        
                        print $_;
                        print "\n";
                        
                        
                        # add line to file buffer
                        $filebuffer .= $_;              
                        
                        # set changed flag
                        $changed = 1;
                }
        }    
        # check for copyright lines like X-Y                    
        elsif ($_ =~ m/.*[cC]opyright[^\d]*\d\d\d\d\-(\d\d\d\d).*/ ) {
                
                if ($SVNYear > $1) {
                
                        print "CASE 2\n";
                        print "Ok, the 'Last Changed Date' according to SVN is: 
$SVNYear.\n";
                        print "This is a later date than the current copyright 
notice date, which is $1.\n";
                        print "I'll change\n\t'$_'\n\tinto: ";                  
        
                        
                        # make sure only the 'Y', not 'X', in 'X-Y' is changed
                        $_ =~ s/\-$1/\-$SVNYear/;
                        
                        print $_;
                        print "\n";
                        
                        $filebuffer .= $_;
                        $changed = 1;                           
                }
        }
                                                                
        
        # if the line was not changed, it was not a copyright notice,
        # therefore not added yet. So add it to the buffer now.
        if($changed == 0) {
                $filebuffer .= $_;
        }
    }
        
        # end of file reached, now write the buffer back to file again.
        # this code is taken from the Perl Cookbook.
        seek(FILE, 0, 0)               or die "can't seek to start of $file: 
$!";
                print FILE $filebuffer         or die "can't print to $file: 
$!";        
                truncate(FILE, tell(FILE))     or die "can't truncate $file: 
$!";        
                close(FILE)                    or die "can't close $file: $!";  
         
    
    print "Handled file $file\n";
    push @handled_files, $filename;
    
    
}

if (@ARGV < 1) {
        print <<'USAGE' 

Usage: perl changeCopyright <directory>

        Updates the copyright notice to the year from SVN according to the 
'Last Changed Date' for all files in <directory>.
        Please give the FULL path to the directory (on windows this could be 
'c:\parrot')
        
USAGE

}
else {
        my @DIRLIST = ();
        push @DIRLIST, $ARGV[0];
        find(\&process_file, @DIRLIST);
        
        if(@unhandled_files) {
                open UNHANDLED, "> unhandledfiles.txt";
                
                print "Unhandled files:\n";
                while(@unhandled_files) {
                        my $file = shift @unhandled_files;
                        print UNHANDLED "$file\n";
                }
                
                close UNHANDLED;
                
        }
        
        if(@handled_files) {
                open HANDLED, "> handledfiles.txt";
                
                print "handled files:\n";
                while(@handled_files) {
                        my $file = shift @handled_files;
                        print HANDLED "$file\n";
                }
                
                close HANDLED;
        }
}


# TODO: compile a list of files that has been changed by this script. 

Reply via email to