Querying MS Visual Source Safe in Perl - Counting DIFFs

Posted by jonathan on August 15, 2007

The following Perl code automates MS Visual Source Safe to get the stats on check-ins. The input should be a list of files from the output of my other script.



#!/usr/bin/perl -w
use strict;
 
# Read a list of check-ins and call 'ss Diff' to get what was checked-in
 
$ENV{'SSDIR'} = "<source safe network folder>";
my $project = "<project folder>";
my $checkInsFile = "<output from first perl script>";
 
# Read in check-ins from file
open( checkIns, $checkInsFile );
while( <checkIns> ) {
    
    # Parse out the details from the check-in
    my( $file, $ver, $use, $date, $com );
    if( m/^(.*)\t(.*)\t(.*)\t(.*)\t(.*)$/ ) {
        ( $file, $ver, $use, $date, $com ) = ($1, $2, $3, $4, $5);
    }
    
    # Put any check for conditions here
  
    # Check for some date range
    
    # Check for some file pattern
    
    # Check for some comment pattern
        
    # Summed totals for this check-in
    my $added   = 0;
    my $changed = 0;
    my $deleted = 0;
    
    # Special case version 1 to get the file line count of Version 1 (Check-in)
    if( $ver == '1' ) {
        
        # Get linecount for version 1 of file
        my $command = "ss View \$/$project/$file -V$ver|";
        open( ssView, $command );
        while( <ssView> ) {
            $added++;
        }
        close( ssView );
        
    }
    else {
        
        # Open a Unix diff from version-1 to version
        my $verMinus1 = $ver - 1;
        my $command = "ss Diff -DU \$/$project/$file -V$verMinus1~$ver|";
        open( ssDiff, $command );
        
        while( <ssDiff> ) {
            
            # Match for "number[a|d|c]number" at the start of a line
            if( m/^(\d+),?(\d*)([acd])(\d+),?(\d*)$/ ) {
                
                # Added
                if( $3 eq "a" ) {
                    $added += ($5 gt "" ? $5 : $4) - $4 + 1;
                }
        
                # Changed
                if( $3 eq "c" ) {
                    $changed += ($5 gt "" ? $5 : $4) - $4 + 1;
                }
        
                # Deleted
                if( $3 eq "d" ) {
                    $deleted += ($5 gt "" ? $5 : $4) - $4 + 1;
                }
            }
        }
        
        close( ssDiff );
    }
    
    # Print check-in details + edit details
    print "$file\t$ver\t$use\t$date\t$added\t$changed\t$deleted\t$com\n";
    #print "Totals for ${file};$ver ($use) on $date added: $added changed: $changed deleted: $deleted\n";
}
 
# Done
exit 0;

Querying MS Visual Source Safe in Perl - List Check-Ins

Posted by jonathan on August 15, 2007

The following code needs Visual Source Safe to be installed, and produces a list of all file versions for the project folder set up as ‘my $project’.  Remember to set the network folder where the ss.ini file lives.

The program outputs a tab separated list of:
filename->version->user->date->comment.

Enjoy! My next post will take this file and dump out the lines added, changed, deleted for whatever subset of the check-ins that you are interested in.



#!/usr/bin/perl -w
use strict;
 
#-------------------------------------------------------------------
# Given a source project folder, list the files and check-in details
#
# ToDo:
# Progress indicator
# Usage output.
# Take command-line arguments
#-------------------------------------------------------------------
 
$ENV{'SSDIR'} = "<source safe folder on network>";
my $project = "<source safe project>";
 
# Start with the project folder
my @files;
open( ssFiles, "ss Dir \$/$project|");
 
# Iterate through the list of files
while( <ssFiles> ) {
 
    # Get all the cpp and .h files
    if( /.*\.cpp/ || /.*\.h/ ) {
        push @files, $_;
    }
}
close( ssFiles );
 
# Print a header line
print "Filename\tVersion\tDeveloper\tDate\tComment\n";
 
# Iterate over the list of chomp'ed files (removes trailing newlines)
chomp( @files );
foreach( @files ) {
 
    # What we are looking at
    my $file = $_;
    my $lastver = -1;
    my( $ver, $use, $date, $com );
    
    # Get history of versions for file, excluding build labels
    open( ssHistory, "ss History \$/$project/$_|");
    while( <ssHistory> ) {
        
        # Get version number
        if( m/^.*Version (\d*) .*/ ) {
            $ver = $1;
        }
        
        # Get user name
        if( m/^.*User\: (\w*).*Date\:.* (\d+)\/(\d*)\/(\d*) .*Time.*/ ) {
            $use = $1;
            $date = "$2/$3/20$4";
        }
        
        # Get comment        
        if( m/^.*Comment\: (.*).*$/ ) {
            $com = $1;
        }
        
        # If we have all vars populated and haven't already printed this version check-in
        # then go ahead and print it out
        if( /^$/ && $ver && $use && $lastver!=$ver ) {  # $com optional
            $lastver = $ver;
            print "$file\t$ver\t$use\t$date\t$com\n";
            
            # We are done with this data now
            $ver = $use = $date = $com = undef;
        }
    }
 
    # Close command stream    
    close( ssHistory );
 
}
exit 0;