2009-08-27 139 views
3

如果我希望基本上grep知識庫中的每一行,有沒有辦法做到這一點?我知道這對於大型項目來說需要很長時間。如何搜索整個CVS存儲庫(所有分支機構/歷史/評論)?

如果不是全部包容,至少只是當前分支及其整個源歷史?

編輯:我應該更加明確。 如果我沒有直接訪問CVS存儲庫所在的服務器,該怎麼辦?所以我不能直接 grep具有CVS存儲庫的文件系統。

+0

無法訪問存儲庫是一個相當大的事情,省略,你不覺得嗎?但是,除非您使用pserver,否則您的IT部門經歷了很長時間,您可能有權訪問存儲庫 - 只是訪問不方便。請編輯您的問題並添加CVS/Root文件的內容(您可以在工作樹的任何目錄中找到它)。如果您不想讓人們知道您的網絡,請將所有主機名引用替換爲foo.example.com,並根據需要替換目錄名稱。但別改變別的。 – kdgregory 2009-08-28 01:37:49

+0

對不起,我不知道標準的CVS設置是什麼。我一直在使用Subversion,而且我最後一次使用CVS的時間已經超過8年。我正在使用pserver。我試着在主機上閃爍,但沒有運氣。我會詢問有關建立一個帳戶,因爲這似乎是最好的方式。 – 2009-08-28 11:06:41

回答

0

這取決於你在找什麼。 CVS版本文件以明文形式包含了文件發生過的所有編輯。因此,如果您只是在查找包含特定單詞的所有文件,請對存儲庫執行遞歸grep。

如果您正在尋找包含這些單詞的特定版本,那麼您將不得不從版本庫中提取版本,這很昂貴。但是,如果您可以通過刷新存儲庫來限制文件集,那麼它並不是那麼糟糕。

1

沒有辦法使用標準CVS工具來訪問存儲庫。一個第三方工具可以做到這一點(我不知道其中一個,儘管CS-CVS似乎是claim to),但是要以編程方式進行,您必須在所有相關文件上執行CVS日誌,然後檢索並在日誌中搜索由CVS報告的每個版本(CVS日誌是CVS中的命令行選項,顯示任何文件的修訂歷史記錄,但不會顯示內容)。

+0

+1,thx。很高興知道。 – 2009-08-28 15:32:59

1

這是我最近使用的情況下,我沒有訪問服務器的情況。它似乎在那個時候工作。從工作副本中調用它,在PATH中使用CVS。請注意,這不會搜索提交消息,但您可以簡單地grep'cvs log'。

#!/usr/bin/perl 

# Searches CVS diffs and first revisions behind the current working 
# directory for an expression (perlre syntax). 

# Synopsis: cvsgrep [-n] <search-expression> [<file_1> ... <file_n>] 

# -n means that contents of matching files should not be printed to stdout. 

use Getopt::Std; 

my %options=(); 
getopts("n",\%options); 
my $no_content_dump=$options{"n"}; 

my $search_term=shift 
    or die "Error: usage is: cvsgrep [-n] <search-expression>". 
    " [<file_1> ... <file_n>]"; 

sub quote_fn 
{ 
    my $fn=shift; 
    $fn =~ s/\'/\'\"\'\"\'/g; 
    "'".$fn."'"; 
} 

my $args_str; 
while(@ARGV) 
{ 
    my $arg=shift; 
    $args_str.=' ' if $args_str; 
    $args_str.=&quote_fn($arg); 
} 

print 
    "Searching for term: $search_term", 
    ($args_str?" in: $args_str":""), 
    "\n"; 

open CVSLOGH,"cvs log -N $args_str|" or die "Cannot execute cvs log: $!"; 

my @files_revisions=(); 

my $cur_file; 
my $cur_revision; 

while(<CVSLOGH>) 
{ 
    chop; 
    if(/^Working file\:\s*(.*)$/) 
    { 
     $cur_file=$1; 
     $cur_revision=''; 
    } 
    elsif(/^revision\s+(.*)$/) 
    { 
     $cur_revision=$1; 
    } 
    elsif((/^\=\=\=\=/ || /^\-\-\-\-/) && $cur_revision) 
    { 
     push @files_revisions,{file=>$cur_file,rev=>$cur_revision}; 
    } 
} 

close CVSLOGH; 

my $matchcount=0; 
my $count=0; 
my $progress_msg="Scanned %d out of %d commit(s)\r"; 
my $erase_ln=(" " x (length($progress_msg)+20)) . "\r"; 

foreach my $file_revision(@files_revisions) 
{ 
    printf($progress_msg,$count++,scalar(@files_revisions)); 

    my($file,$rev) = ($file_revision->{file},$file_revision->{rev}); 

    $rev =~ /^(.*\.)([0-9]+)/; 
    my $revbase=$1; 
    my $revlastdigit=$2; 
    my $rev1=$revbase.($revlastdigit - 1); 
    my $diffcommand = "cvs diff -N -r $rev1 -r $rev ".&quote_fn($file); 
    open CVSDIFFH,"$diffcommand|" or die "Cannot execute cvs diff: $!"; 

    my $diffresult; 
    while(<CVSDIFFH>) 
    { 
     if(/^[\<\>]/) 
     { 
      s/^.//; 
      $diffresult.=$_; 
     } 
    } 
    close CVSDIFFH; 

    if($diffresult =~ /$search_term/s) 
    { 
     print "${erase_ln}FOUND: in diff for $file $rev1:$rev\n"; 
     $matchcount++; 
     system($diffcommand) unless $no_content_dump; 
    } 
} 

print "${erase_ln}Done ($matchcount match(es)).\n";