代码之家  ›  专栏  ›  技术社区  ›  Keith Bentrup

如何搜索整个CVS存储库(所有分支/历史记录/注释)?

  •  3
  • Keith Bentrup  · 技术社区  · 15 年前

    如果我想从本质上grep存储库中的每一行,有没有办法?我知道这对于大型项目来说需要很长时间。

    编辑:我应该更明确一些。 如果我不能直接访问CVS存储库所在的服务器,该怎么办? 直接地

    3 回复  |  直到 15 年前
        1
  •  1
  •   Yishai    15 年前

    在没有访问存储库的情况下,使用标准CVS工具无法做到这一点。第三方工具可能会做到这一点(我不知道有一个,尽管CS-CVS似乎可以做到) claim to ),但要以编程方式执行此操作,您必须在所有相关文件上执行CVS日志,然后在日志中检索和搜索CVS报告的每个版本(CVS日志是CVS中的一个命令行选项,它显示任何文件的修订历史,但不显示内容)。

        2
  •  1
  •   Raimund Steger    12 年前

    #!/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";
    
        3
  •  0
  •   kdgregory    15 年前

    这取决于你在找什么。CVS版本文件以明文形式包含对该文件所做的所有编辑。因此,如果您只是查找包含特定单词的所有文件,请在存储库上执行递归grep。

    如果要查找包含这些单词的特定版本,则必须从存储库中提取这些版本,这是非常昂贵的。但是,如果您可以通过对存储库进行灰显来限制文件集,那么就没有那么糟糕了。