Pergunta
Estou ciente deste comando:
cvs log -N -w<userid> -d"1 day ago"
Infelizmente isso gera um relatório formatado com muita newlines em que, tal que o arquivo-caminho, o arquivo-versão e o comentário de texto são todos em linhas separadas. Por isso, é difícil de digitalizá-lo para todas as ocorrências de comentário de texto, (por exemplo, grep), e correlacionar os jogos para o arquivo / versão.
(Note-se que a saída do log seria perfeitamente aceitável, se apenas cvs poderia executar a filtragem nativamente.)
EDIT: Exemplo de saída. Um bloco de texto como este é relatado para cada arquivo de repositório:
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. =============================================================================
Solução
As opções -w
parece funcionar melhor com a opção -S
. Caso contrário, há resultados adicionais que não parecem relacionadas com o ID de usuário. Talvez alguém pode explicar isso.
cvs log -N -S -w<userid> -d"1 day ago"
Com que eu fui ficando razoável sucesso tubulação para grep:
cvs log -N -S -w<userid> -d"1 day ago" | grep -B14 "some text" > afile
Estou redirecionar a saída para um arquivo desde o log do cvs é barulhento e eu não tenho certeza de como fazê-lo calar. Suponho que uma alternativa é redirecionar o stderr para /dev/null
.
Outras dicas
Você quer cvsps - o que irá gerar patches de da história CVS. Então, você deve ter apenas uma instância do seu comentário na saída cvsps, com os arquivos listados ordenadamente abaixo
Meu primeiro pensamento foi usar egrep (ou -E grep, eu acho) para procurar vários padrões, tais como:
<Cmd> | egrep 'Filename:|Version:|Comment:'
mas depois percebi que queria filtro de forma mais inteligente.
Para esse fim, gostaria de usar awk (ou perl) para processar a linha por linha de saída, definindo uma variável de eco quando você encontrar uma seção de interesses; pseudocode aqui:
# 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
Aqui está o que eu fiz - um simples script de Java:
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();
}
}
}
E aqui está como eu usei-o:
cvs log -N -S -washamsut | java ParseCVSLog GS-242
Este script de comandos e gawk me ajuda a encontrar apenas o nome do arquivo, a data ea linha de comentário de cada entrada de registro.
cvs log -N -S -b -w<userid> -d ">1 day ago" 2>/dev/null | gawk 'BEGIN{out=0;} /^Working file:/ { print $0; } /^date:/ { out=1; } /^===/ { print ""; out=0; } (out==1){print $0;}'
Esta pode ser a maneira exagero, mas você poderia usar git-cvsimport para importar o histórico CVS para um repositório git e busca-lo usando ferramentas do git. Não apenas você pode procurar texto dentro de mensagens de commit, mas você também pode procurar o código que já foi adicionado ou removidos a partir de arquivos em seu repositório.
CVSSearch pode ajudar, mas é uma aplicação CGI: '(