tags:

views:

3406

answers:

6

I am aware of this command: cvs log -N -w<userid> -d"1 day ago"

Unfortunately this generates a formatted report with lots of newlines in it, such that the file-path, the file-version, and the comment-text are all on separate lines. Therefore it is difficult to scan it for all occurrences of comment text, (eg, grep), and correlate the matches to file/version.

(Note that the log output would be perfectly acceptable, if only cvs could perform the filtering natively.)

EDIT: Sample output. A block of text like this is reported for each repository file:


RCS file: /data/cvs/dps/build.xml,v
Working file: build.xml
head: 1.49
branch:
locks: strict
access list:
keyword substitution: kv
total revisions: 57;    selected revisions: 1
description:
----------------------------
revision 1.48
date: 2008/07/09 17:17:32;  author: noec;  state: Exp;  lines: +2 -2
Fixed src.jar references
----------------------------
revision 1.47
date: 2008/07/03 13:13:14;  author: noec;  state: Exp;  lines: +1 -1
Fixed common-src.jar reference.
=============================================================================
A: 

This might be way overkill, but you could use git-cvsimport to import the CVS history to a Git repository and search it using Git's tools. Not only can you search for text within commit messages, but you can also search for code that has ever been added or removed from files in your repository.

Greg Hewgill
A: 

CVSSearch might help, but it's a CGI application :'(

Mez
+1  A: 

My first thoughts were to use egrep (or grep -E, I think) to search for multiple patterns such as:

<Cmd> | egrep 'Filename:|Version:|Comment:'

but then I realised you wanted to filter more intelligently.

To that end, I would use awk (or perl) to process the output line-by-line, setting an echo variable when you find a section of interest; pseudocode here:

# Assume the sections are of the format:
#   Filename: <filename>
#   Version:  <version>
#   Comment:  <comment>
#             <more comment>

Set echo to false
While more lines left
    Get line
    If line starts with "Filename: " and <filename> is of interest
        Set echo to true
    If line starts with "Filename: " and <filename> is not of interest
        Set echo to false
    If echo is true
        Output line
End while
paxdiablo
The tricky part of a post-processing solution is that the content-of-interest is in the later part of the text blocks. Therefore it would be necessary to buffer up each block, then discard or output it. I believe awk can do this, but it would probably involve a multi-day project for me.
Chris Noe
+2  A: 

The -w options seems to work better with the -S option. Otherwise there are additional results which don't seem related to the userid. Perhaps someone can explain it.

cvs log -N -S -w -d"1 day ago"

With that I have been getting reasonable success piping it to grep:

cvs log -N -S -w -d"1 day ago" | grep -B14 "some text" > afile

I'm redirecting output to a file since the cvs log is noisy and I'm not sure how to make it quite. I suppose an alternative is to redirect the stderr to /dev/null.

s_t_e_v_e
That's awesome Steve. I wasn't aware of the -B grep option: "print NUM lines of leading context". So with the 15-line report that cvs log generates for each file (the comment being the 15th), -B14 gives me the whole block for each matching file.
Chris Noe
Obviously this works best when the text you are searching for is in the first line, but its a start.
s_t_e_v_e
by the way, cvs log -N -S -w -d"1 day ago" will look for entries older thatn 1 day ago by default. I think what you want is this -d">1 day ago"
s_t_e_v_e
A: 

Here is what I did - a simple Java script: import java.io.IOException;

public class ParseCVSLog {

public static final String CVS_LOG_FILE_SEPARATOR = "=============================================================================";
public static final String CVS_LOG_REVISION_SEPARATOR = "----------------------------";
public static final String CVS_LOG_HEADER_FILE_NAME = "Working file";
public static final String CVS_LOG_VERSION_PREFIX = "revision";

public static void main(String[] args) throws IOException
{
    String searchString = args[0];

    System.out.println( "SEARCHING FOR: " + searchString );

    StringBuffer cvsLogOutputBuffer = new StringBuffer();
    byte[] bytes = new byte[1024];
    int numBytesRead = 0;
    while( (numBytesRead = System.in.read( bytes )) > 0 )
    {
        String bytesString = new String(bytes, 0,  numBytesRead);
        cvsLogOutputBuffer.append( bytesString );
    }

    String cvsLogOutput = cvsLogOutputBuffer.toString();

    String newLine = System.getProperty("line.separator");
    String[] fileArray = cvsLogOutput.split( CVS_LOG_FILE_SEPARATOR );


    for ( String fileRecord : fileArray )
    {
        if ( !fileRecord.contains( searchString ) )
        {
            continue;
        }

        String[] revisionArray = fileRecord.split( CVS_LOG_REVISION_SEPARATOR );
        String[] fileHeaderLineArray = revisionArray[ 0 ].split( newLine );
        String fileName = "";
        for ( String fileHeadeLine : fileHeaderLineArray )
        {
            if ( fileHeadeLine.contains( CVS_LOG_HEADER_FILE_NAME ) )
            {
                fileName = fileHeadeLine.split( ": " )[ 1 ];
                break;
            }
        }
        System.out.print( fileName );
        for ( int i = 1; i < revisionArray.length; i++ )
        {
            String versionRecord = revisionArray[ i ];
            if ( !versionRecord.contains( searchString ) )
            {
                continue;
            }
            String[] versionLineArray = versionRecord.split( newLine );
            for ( String versionLine : versionLineArray )
            {
                if ( versionLine.contains( CVS_LOG_VERSION_PREFIX ) )
                {
                    System.out.print( " " + versionLine.split( " " )[ 1 ] );
                }
            }

        }
        System.out.println();
    }
}

}

And here is how I used it: cvs log -N -S -washamsut | java ParseCVSLog GS-242

A: 

You want cvsps - which will generate patchsets from CVS history. Then, you should only have one instance of your comment in the cvsps output, with the files listed neatly below it :)

[Eds: I know this is an old topic - delete if you wish]

Tim West