info-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: CVS Statistics


From: Jerry Nairn
Subject: RE: CVS Statistics
Date: Mon, 26 Nov 2001 14:50:01 -0800

> From: address@hidden [mailto:address@hidden
> Sent: Monday, November 26, 2001 2:02 AM

> I would like to know the statistics on a particular file ( say test.c
> ) from one version to another version ( say from 1.2 to 1.7 ).
> 
> So for instance if i run the command/script 
> <cvs_command> -R1.2 -R2.7 test.c 
> i would like to know the number of lines added, deleted and modified
> between version 1.2 to 1.7 for test.c

Here's a perl script to do this.
Jerry

=====================================================
#!/usr/bin/perl -w
#
# diffcounter - Jerry Nairn, address@hidden
# based on diffdetailer by Josh Geller.
#

use strict;

use Cwd;

use vars qw(
            $infile
            $outfile
            $first_arg
            $second_arg
            $modules
            $workdir
            $pwd
            %extension
            );

&input;
&seperate;
&cleanup;

sub input {
    my @array;
    if( ! ( $#ARGV > 1 ) ) {
        print STDERR "Usage: $0 FIRST_ARG SECOND_ARG MODULE(S)\n";
        print STDERR "Where ARGs are of the form -rTAG or -Ddate\n";
        exit 1;
    } else {
        $first_arg = shift @ARGV;
        if ( $first_arg !~ /^\-/ ) { $first_arg = "-r" . $first_arg };
        $second_arg = shift @ARGV;
        if ( $second_arg !~ /^\-/ ) { $second_arg = "-r" . $second_arg };
        $modules = join " ",@ARGV;
        $infile = "/tmp/temp_$$";
        $workdir = "/tmp/WORK_$$";
        mkdir($workdir, 0755);
    }
    $pwd = getcwd();
    chdir($workdir);
    system("cd $workdir; cvs -Q checkout $second_arg $modules");
    open(INPIPE, "cvs -Q rdiff -s $first_arg $second_arg $modules|") 
       || die "Could not open pipe: $! \n";
    @array = <INPIPE>;
    close(INPIPE);
    open(INFILE, ">$infile") || die "Could not open $infile for writing: $!
\n";
    foreach (@array) {
        chomp;
        print INFILE "$_ \n";
    }
    close(INFILE);
}

sub seperate {

    my @new;
    my @removed;
    my @changed;
    my @unknown;
    my $numlines;
    my $addedlines = 0;
    my $removedlines = 0;
    my $modifiedlines = 0;
    my $print_arg1 = substr(${first_arg},2);
    my $print_arg2 = substr(${second_arg},2);
    my $report = "change_count.txt";

    if ( substr(${second_arg},0,2) eq "-r" ) {
        $report = $print_arg2 . "_change_count.txt";
    }

    open(INFILE, "<$infile") || die "Could not open $infile for reading: $!
\n";
    chdir $pwd;
    open(OUTFILE, ">$report") || die "Could not open $report for writing: $!
\n";
    foreach (<INFILE>) {
        chomp;
        if(m/^.*\s(\S+)\s\w+\snew.*revision\s?([0-9].*[0-9])?\s*$/) {
            push @new, "$1                    $2";
        } elsif(m/^.*\s(\S+)\sis\sremoved;\s(.*)$/) {
            push @removed, "$1 has been removed, $2";
        } elsif(m/^.*\s(\S+)\schanged.*revision\s?([0-9].*[0-9])?\s*$/) {
            push @changed, "$1                    $2";
        } else {
            push @unknown, $_;
        }
    }
    if ( @new ) {
        print OUTFILE <<EOT;
###
### Files added before $print_arg2 
### (not in $print_arg1):                          Revision:

EOT
        foreach(@new) {
            m/(\S+)\s+(\S+)/;
            $numlines = countlines($1,"-r$2",1);
            print OUTFILE "$_\n";
            print OUTFILE "$numlines\n";
        }
    }
    if ( @removed ) {
        print OUTFILE <<EOT;

###
### Files removed after $print_arg1
### (not in $print_arg2):

EOT
        foreach(@removed) {
            m/(\S+) has been removed.*/;
            $numlines = countlines($1,$first_arg,0);
            print OUTFILE "$_\n";
            print OUTFILE "$numlines\n";
        }
    }
    if ( @changed ) {
        print OUTFILE <<EOT;

###
### Files changed between 
### $print_arg1 and $print_arg2:                    Revisions:

EOT
        foreach(@changed) {
            m/(\S+)\s+(\S+) to (\S+)/;
            $numlines = countdiff($1,$2,$3);
            print OUTFILE "$_\n";
            print OUTFILE "$numlines\n";
        }
    }
    if ( @unknown ) {
        print OUTFILE <<EOT;

###
### Lines from cvs rdiff which I could not interpret:

EOT
        foreach(@unknown) {
            print OUTFILE "$_\n";
        }
    }
    if ( %extension ) {
        print OUTFILE <<EOT;

###
### Summary of Affected Lines of Code, by File Name Extension:
##        .ext|  deleted|    added| modified|
EOT
    my $ext;
    my $sumtotal;

        foreach $ext ( sort keys %extension ) {
            printf OUTFILE "%14s|%9d|%9d|%9d|\n", $ext,
                       address@hidden,
                       address@hidden,
                       address@hidden;
            $sumtotal += address@hidden +
                         address@hidden +
                         address@hidden;
        }
        print OUTFILE "\n### $sumtotal Total Lines Affected, $print_arg1 to
$print_arg2\n";
    }

    close OUTFILE;
}

sub cleanup {
    system("rm -rf $infile $workdir");
}

sub countlines {
    my $filename = shift;
    my $revision = shift;
    my $newfile = shift;
    my $result = "(binary file)";
    my $lines = 0;
    my $ext;

    chdir($workdir);
    system("cvs -Q -f up $revision $filename");
    if ( iscvstext($filename) ) {
        $lines = `wc -l < "$filename" | tr -d " "`;
        chomp $lines;
        $result = "($lines total lines)";
        $ext = get_ext($filename);
        if ( $newfile ) {
            &ext_count($ext, 0, $lines, 0);
        } else {
            &ext_count($ext, $lines, 0, 0);
        }
    }
    chdir($pwd);
    return $result;
}

sub countdiff {
    my $filename = shift;
    my $revision1 = shift;
    my $revision2 = shift;
    my $result = "(binary file)";
    my @diffout;
    my $line;
    my $ext;
    my $linescut = 0;
    my $linesnew = 0;
    my $linesmod = 0;
    my $inmod = 0;
    my $cuthere = 0;

    chdir($workdir);
    if ( iscvstext($filename) ) {
        @diffout = `cvs -Q diff -u -r$revision1 -r$revision2 $filename`;
        while ( $line = shift @diffout ) {
            if ( $line =~ /^\+\+\+.*/ ) {
                last;
            }
        }
# A stretch of /^\-/ lines followed by the same number of /^\+/ lines
# is really a set of modified lines, not one set of deleted and one
# set of added lines.
        while ( $line = shift @diffout ) {
            if ( $line =~ /^\-.*/ ) {
# found a removed or modified line
# we are probably in a modification
                $inmod = 1;
                $cuthere++;
            } elsif ( $line =~ /^\+.*/ ) {
# found an added or modified line
                if ( $inmod && $cuthere ) {
# decided it was modified
                    $cuthere--;
                    $linesmod++;
                } else {
# decided it was added
                    $linescut += $cuthere;
                    $cuthere = $inmod = 0;
                    $linesnew++;
                }
            } elsif ( $line =~ /^(\s|\@).*/ ) { 
# found an unchanged line
                $linescut += $cuthere;
                $cuthere = $inmod = 0;
            }
        }
        $result = "(";
        if ( $linescut ) {
            $result .= "$linescut removed";
        }
        if ( $linesnew ) {
            if ( $linescut ) {
                $result .= ", ";
            }
            $result .= "$linesnew added";
        }
        if ( $linesmod ) {
            if ( $linesnew || $linescut ) {
                $result .= ", ";
            }
            $result .= "$linesmod modified";
        }
        $result .= " lines)";
        $ext = get_ext($filename);
        &ext_count($ext, $linescut, $linesnew, $linesmod);
    }
    chdir($pwd);
    return $result;
}

sub get_ext {
    my $filename = shift;
    my $ext;

    ($ext = $filename) =~ s/^.*(\.[^\.]+)$/$1/;
    if ( $ext eq $filename ) {
        $ext = "NONE";
    }
    return $ext;
}

sub iscvstext {
    my $filename = shift;

    chdir($workdir);
    my @options= grep s/^\s+Sticky Options:\s+(\S+)\s*$/$1/, `cvs stat
"${filename}"`;
    return 0 if ( $options[0] ne "(none)" );
    return 1;
}

sub ext_count {
    my $ext = shift;
    my $cutlines = shift;
    my $newlines = shift;
    my $modlines = shift;
    my @extlines = ($cutlines, $newlines, $modlines);

    if ( $extension{$ext} ) {
        address@hidden += $extlines[0];
        address@hidden += $extlines[1];
        address@hidden += $extlines[2];
    } else {
        address@hidden = $extlines[0];
        address@hidden = $extlines[1];
        address@hidden = $extlines[2];
    }
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]