I receive numerous complaints that my attachment was not generally
accessible because "BINHEX isn't as well known as Mime encoding". :(
Sorry. Although I've been software engineering for 20+ years, I'm not
a very sophisticated software user. I know enough about my e-mail
program to find the Attach button -- didn't know there were so many
options.
I've repeated my original message to provide context. The awk script
is appended at the end. I hope emailer-induced line breaks don't cause
too much heartache.
By the way, I forgot to mention before that this script was developed
on a Sun4 (SunOS 5.6) with CVS 1.10 'Halibut'. We do not use the
client/server option. If your system differs from ours then there
is a risk that your cvs log output is different than mine -- thereby
breaking the awk script.
==============================================================
I slapped together an awk script a couple of weeks ago to extract some
simple source metrics from the cvs log. I noticed that the log entry for
each revision is accompanied by the number of lines added and deleted.
However, these counts don't appear to be useful when files are added or
removed. The best my tool can do is identify add and remove events so the
user can use some other method to get the necessary information.
For what its worth, I think of these more as "source metrics" than "code
metrics".
Here's how you run my tool on a UNIX system:
cvs -q log -N -d"dateRange" | log-summary.awk
This tool reports
number of lines added to text files
number of lines deleted from text files
number of programmers doing commits (and their names)
number of binary files in repository [not limited to "dateRange"]
number of binary files modified (and their names)
number of binary files added (and their names)
number of binary files removed (and their names)
number of text files modified (and their names)
number of text files added (and their names)
number of text files removed (and their names)
By [my] definition, binary files are those with -kb keyword substitution;
text files are those without -kb.
The number of lines added and deleted from text files DO NOT include
contributions from "cvs add" and "cvs remove".
The number of binary files in the repository is the only item reported that
is not limited to the "dateRange".
We don't typically have subdirectories within our cvs modules, so this tool
is not adequately tested for that circumstance.
I'm pretty sure I don't handle files that go into the Attic and later come
out.
I would love to hear of any other deficiencies that y'all find in this
tool. Improvements and bug fixes would be grand!
==================================
#! /bin/awk -f
# @(#)$Header: /sw/cvsroot/cvs-tools/log-summary.awk,v 1.3 2000/01/18
22:06:29 don Exp $
# This awk script summarizes the output of 'cvs log -N'.
# The summary output contains the following information:
# Number of lines added (not including newly added files).
# Number of lines deleted (not including newly removed files).
# Number of programmers who committed files and their names.
# Number of binary files in the repository and their names.
# Number of binary files modified and the names of those files.
# Number of binary files added and the names of those files.
# Number of binary files removed and the names of those files.
# Number of text files modified and the names of those files.
# Number of text files added and the names of those files.
# Number of text files removed and the names of those files.
# Binary files (keyword substitution "b") do not contribute to the line
counts.
#
# This awk script assumes that user-generated log message lines obey the
following rules:
# Never begin with "Working file:".
# Never begin with "date:".
# Never consist of "keyword substitution: b".
# Never consist of "revision 1.1".
#
# Omitting the -N option from 'cvs log' has the following effects:
# The script input is unnecessarily enlarged, increasing execution time.
# Tag names must also honor the log message line rules described above.
#
# Initialize state variables.
BEGIN { thisFile = ""; # Name of the current file.
thisFileBinary = 0; # Nonzero if current file is
a binary file.
thisFileModified = 0; # Nonzero if current file
modified.
numLinesAdded = 0; # Number of lines added.
numLinesDeleted = 0; # Number of lines deleted.
numProgrammers = 0; # Number of programmers.
programmers = ""; # Names of all programmers.
numBinaryFiles = 0; # Number of binary files in
the repository.
binaryFiles = ""; # Names of all binary files.
binaryFilesModified = ""; # Names of all modified
binary files.
binaryFilesAdded = ""; # Names of all added binary files.
binaryFilesRemoved = ""; # Names of all removed binary
files.
numBinaryFilesModified = 0; # Number of binary files
modified.
numBinaryFilesAdded = 0; # Number of binary files
added.
numBinaryFilesRemoved = 0; # Number of binary files
removed.
textFilesModified = ""; # Names of all modified text
files.
textFilesAdded = ""; # Names of all added text
files.
textFilesRemoved = ""; # Names of all removed text files.
numTextFilesModified = 0; # Number of text files
modified.
numTextFilesAdded = 0; # Number of text files added.
numTextFilesRemoved = 0; # Number of text files
removed.
sLinesAdded = "s"; # Assume number of lines
added is plural.
sLinesDeleted = "s"; # Assume number of lines
deleted is plural.
sTextFilesModified = "s"; # Assume number of text files
modified is plural.
sTextFilesAdded = "s"; # Assume number of text files
added is plural.
sTextFilesRemoved = "s"; # Assume number of text files
removed is plural.
sFilesBinary = "s"; # Assume number of binary
files is plural.
sBinaryFilesModified = "s"; # Assume number of binary
files modified is plural.
sBinaryFilesAdded = "s"; # Assume number of binary
files added is plural.
sBinaryFilesRemoved = "s"; # Assume number of binary
files removed is plural.
sProgrammers = "s"; # Assume number of
programmers is plural.
}
# Recognize the start of another file in the cvs log report.
/^Working file:/ { thisFile = $3;
thisFileBinary = 0;
thisFileModified = 0;
}
# Recognize binary files.
/^keyword substitution: b$/ {
thisFileBinary = 1;
numBinaryFiles++;
if (binaryFiles != "") binaryFiles = sprintf("%s,",
binaryFiles);
binaryFiles = sprintf("%s%s", binaryFiles, thisFile);
}
# Recognize the initial version of a file.
/^revision 1\.1$/ { if (thisFileBinary == 0) {
numTextFilesAdded++;
if (textFilesAdded != "") textFilesAdded =
sprintf("%s,",textFilesAdded);
textFilesAdded = sprintf("%s%s", textFilesAdded,
thisFile);
}
else {
numBinaryFilesAdded++;
if (binaryFilesAdded != "") binaryFilesAdded =
sprintf("%s,",binaryFilesAdded);
binaryFilesAdded = sprintf("%s%s", binaryFilesAdded,
thisFile);
}
}
# Parse the 'cvs commit' information.
/^date:/ { thisProgrammer = substr($5,1,length($5)-1);
if (programmerArray[thisProgrammer] == 0) {
numProgrammers++;
if (programmers != "") programmers =
sprintf("%s,",programmers);
programmers = sprintf("%s%s", programmers,
thisProgrammer);
programmerArray[thisProgrammer] = 1;
}
if ($7 == "dead;") {
# Recognize that the file has been removed.
if (thisFileBinary == 0) {
numTextFilesRemoved++;
if (textFilesRemoved != "") textFilesRemoved =
sprintf("%s,",textFilesRemoved);
textFilesRemoved = sprintf("%s%s", textFilesRemoved,
thisFile);
}
else {
numBinaryFilesRemoved++;
if (binaryFilesRemoved != "") binaryFilesRemoved =
sprintf("%s,",binaryFilesRemoved);
binaryFilesRemoved = sprintf("%s%s",
binaryFilesRemoved, thisFile);
}
}
else {
# Extract the number of lines added and deleted.
if (NF >= 9) {
if (thisFileBinary == 0) {
lines = substr($9,2);
numLinesAdded += lines;
if (thisFileModified == 0) {
numTextFilesModified++;
if (textFilesModified != "") textFilesModified =
sprintf("%s,",textFilesModified);
textFilesModified =
sprintf("%s%s",textFilesModified,thisFile);
thisFileModified = 1;
}
}
else {
if (thisFileModified == 0) {
numBinaryFilesModified++;
if (binaryFilesModified != "") binaryFilesModified
= sprintf("%s,",binaryFilesModified);
binaryFilesModified =
sprintf("%s%s",binaryFilesModified,thisFile);
thisFileModified = 1;
}
}
}
if (NF >= 10) {
if (thisFileBinary == 0) {
lines = substr($10,2);
numLinesDeleted += lines;
if (thisFileModified == 0) {
numTextFilesModified++;
if (textFilesModified != "") textFilesModified =
sprintf("%s,",textFilesModified);
textFilesModified =
sprintf("%s%s",textFilesModified,thisFile);
thisFileModified = 1;
}
}
else {
if (thisFileModified == 0) {
numBinaryFilesModified++;
if (binaryFilesModified != "") binaryFilesModified
= sprintf("%s,",binaryFilesModified);
binaryFilesModified =
sprintf("%s%s",binaryFilesModified,thisFile);
thisFileModified = 1;
}
}
}
}
}
# Print summary.
END { if (numLinesAdded == 1)
sLinesAdded = "";
if (numLinesDeleted == 1)
sLinesDeleted = "";
if (numProgrammers == 1)
sProgrammers = "";
if (numTextFilesAdded == 1)
sTextFilesAdded = "";
if (numTextFilesModified == 1)
sTextFilesModified = "";
if (numTextFilesRemoved == 1)
sTextFilesRemoved = "";
if (numBinaryFiles == 1)
sFilesBinary = "";
if (numBinaryFilesAdded == 1)
sBinaryFilesAdded = "";
if (numBinaryFilesModified == 1)
sBinaryFilesModified = "";
if (numBinaryFilesRemoved == 1)
sBinaryFilesRemoved = "";
printf("%d text line%s added.\n", numLinesAdded,
sLinesAdded);
printf("%d text line%s deleted.\n", numLinesDeleted,
sLinesDeleted);
printf("%d programmer%s committed files", numProgrammers,
sProgrammers);
if (numProgrammers == 0)
printf(".\n");
else
printf(": %s\n", programmers);
printf("%d binary file%s in the repository",
numBinaryFiles, sFilesBinary);
if (numBinaryFiles == 0)
printf(".\n");
else
printf(": %s\n", binaryFiles);
printf("%d binary file%s modified",
numBinaryFilesModified, sBinaryFilesModified);
if (numBinaryFilesModified == 0)
printf(".\n");
else
printf(": %s\n", binaryFilesModified);
printf("%d binary file%s added", numBinaryFilesAdded,
sBinaryFilesAdded);
if (numBinaryFilesAdded == 0)
printf(".\n");
else
printf(": %s\n", binaryFilesAdded);
printf("%d binary file%s removed", numBinaryFilesRemoved,
sBinaryFilesRemoved);
if (numBinaryFilesRemoved == 0)
printf(".\n");
else
printf(": %s\n", binaryFilesRemoved);
printf("%d text file%s modified", numTextFilesModified,
sTextFilesModified);
if (numTextFilesModified == 0)
printf(".\n");
else
printf(": %s\n", textFilesModified);
printf("%d text file%s added", numTextFilesAdded,
sTextFilesAdded);
if (numTextFilesAdded == 0)
printf(".\n");
else
printf(": %s\n", textFilesAdded);
printf("%d text file%s removed", numTextFilesRemoved,
sTextFilesRemoved);
if (numTextFilesRemoved == 0)
printf(".\n");
else
printf(": %s\n", textFilesRemoved);
}