解析SVN日志中的更改路径以获取包名

-1 投票
2 回答
762 浏览
提问于 2025-04-17 15:52

我在Linux上运行以下命令,以生成某个版本的详细日志。

svn log -v -r12345 http://svn-remote.com/path

输出结果是:

------------------------------------------------------------------------
r12345 | debajyoti.das@email.com | 2013-02-07 01:27:08 -0800 (Thu, 07 Feb 2013) | 1 line
Changed paths:
   M /PROJECT/CYCLE/branches/DEV_Branch/cycle.agent/src/main/java/com/companyname/cycle/agent/Main.java
   M /PROJECT/CYCLE/branches/DEV_Branch/cycle.agent/src/main/java/com/companyname/cycle/agent/bll/tasks/CycleGroupTask.java
   M /PROJECT/CYCLE/branches/DEV_Branch/cycle.agent/src/main/java/com/companyname/cycle/agent/bll/tasks/CycleProcessTaskBll.java
   M /PROJECT/CYCLE/branches/DEV_Branch/cycle.agent/src/main/java/com/companyname/cycle/agent/bll/tasks/CycleSequenceProcessTaskBll.java
   M /PROJECT/CYCLE/branches/DEV_Branch/cycle.test/src/main/java/com/companyname/cycle/test/bll/MockCycleBll.java
   M /PROJECT/CYCLE/branches/DEV_Branch/pas.cycle/src/main/java/com/companyname/pas/cycle/bll/DasCycleBll.java
   M /PROJECT/CYCLE/branches/DEV_Branch/pas.cycle/src/main/java/com/companyname/pas/cycle/dal/DasCycleDal.java

BUG ID 12345678 - BLAH IMPLEMENTATION IN PROJECT.CYCLE 
------------------------------------------------------------------------

我想从这个日志中提取出每个文件的包名。比如:

PROJECT.CYCLE com.companyname.cycle.agent.bll.tasks CycleGroupTask.java

我该如何写一个perl、python或者shell脚本来实现这个功能,这样使用起来就像这样,例如:

$ perl svnlog.pl 12345 > log.txt

2 个回答

1

我觉得你的Java项目是一个Maven项目:

 awk -F'src/main/java/' 'NF==2{split($1,a,"/");j=p=$2;sub(/.*\//,"",j);sub("/[^/]*$","",p);gsub("/",".",p);print a[2]"."a[3],p,j}' yourlog

用你的例子来测试一下:

kent$  cat f1
------------------------------------------------------------------------
r12345 | debajyoti.das@email.com | 2013-02-07 01:27:08 -0800 (Thu, 07 Feb 2013) | 1 line
Changed paths:
   M /PROJECT/CYCLE/branches/DEV_Branch/cycle.agent/src/main/java/com/companyname/cycle/agent/Main.java
   M /PROJECT/CYCLE/branches/DEV_Branch/cycle.agent/src/main/java/com/companyname/cycle/agent/bll/tasks/CycleGroupTask.java
   M /PROJECT/CYCLE/branches/DEV_Branch/cycle.agent/src/main/java/com/companyname/cycle/agent/bll/tasks/CycleProcessTaskBll.java
   M /PROJECT/CYCLE/branches/DEV_Branch/cycle.agent/src/main/java/com/companyname/cycle/agent/bll/tasks/CycleSequenceProcessTaskBll.java
   M /PROJECT/CYCLE/branches/DEV_Branch/cycle.test/src/main/java/com/companyname/cycle/test/bll/MockCycleBll.java
   M /PROJECT/CYCLE/branches/DEV_Branch/pas.cycle/src/main/java/com/companyname/pas/cycle/bll/DasCycleBll.java
   M /PROJECT/CYCLE/branches/DEV_Branch/pas.cycle/src/main/java/com/companyname/pas/cycle/dal/DasCycleDal.java

BUG ID 12345678 - BLAH IMPLEMENTATION IN PROJECT.CYCLE 
------------------------------------------------------------------------

kent$  awk -F'src/main/java/' 'NF==2{split($1,a,"/");j=p=$2;sub(/.*\//,"",j);sub("/[^/]*$","",p);gsub("/",".",p);print a[2]"."a[3],p,j}' f1
PROJECT.CYCLE com.companyname.cycle.agent Main.java
PROJECT.CYCLE com.companyname.cycle.agent.bll.tasks CycleGroupTask.java
PROJECT.CYCLE com.companyname.cycle.agent.bll.tasks CycleProcessTaskBll.java
PROJECT.CYCLE com.companyname.cycle.agent.bll.tasks CycleSequenceProcessTaskBll.java
PROJECT.CYCLE com.companyname.cycle.test.bll MockCycleBll.java
PROJECT.CYCLE com.companyname.pas.cycle.bll DasCycleBll.java
PROJECT.CYCLE com.companyname.pas.cycle.dal DasCycleDal.java
1

这是一个可以运行 svn log 命令并解析输出的版本。

当然,我没有你的代码库,所以我只能假装执行这个命令,输出结果也是假装的,只是用 cat 命令显示了你的输出,但它是可以工作的。

use strict;

my $revno = shift @ARGV;

die "Usage: $0: svn-revision\n" unless $revno;

my $cmd = "svn log -v -r$revno 'http://svn-remote.com/path'";

open(SVN,"$cmd |") or die "Command '$cmd' Failed : $!\n";

while(<SVN>) {
    chomp;
    if ( /^\s+\S\s\/([^\/]+\/[^\/]+).*[^\/]$/ ) {
        (my $tag = $1) =~ s!/!.!g;
        s!.*/src/main/java/!!;
        my @a =  split(/\//);
        my $file = pop @a;
        print $tag, " ",  join(".", @a), " ",  $file, "\n";
    }
}

这是我的测试输出。

PROJECT.CYCLE com.companyname.cycle.agent Main.java
PROJECT.CYCLE com.companyname.cycle.agent.bll.tasks CycleGroupTask.java
PROJECT.CYCLE com.companyname.cycle.agent.bll.tasks CycleProcessTaskBll.java
PROJECT.CYCLE com.companyname.cycle.agent.bll.tasks CycleSequenceProcessTaskBll.java
PROJECT.CYCLE com.companyname.cycle.test.bll MockCycleBll.java
PROJECT.CYCLE com.companyname.pas.cycle.bll DasCycleBll.java
PROJECT.CYCLE com.companyname.pas.cycle.dal DasCycleDal.java

一个 Maven 代码库里也会有一个 src/test/java 目录 :D,我猜你对这些不感兴趣。


编辑 运行 Perl 代码的主体,基本上是从另一个问题中添加 my $cmd = "sh fake.sh";,得到的结果是:

PROJECT.CYCLE com.companyname.cycle.agent Main.java
PROJECT.CYCLE com.companyname.cycle.agent.bll.tasks CycleGroupTask.java
PROJECT.CYCLE com.companyname.cycle.agent.bll.tasks CycleProcessTaskBll.java
PROJECT.CYCLE com.companyname.cycle.agent.bll.tasks CycleSequenceProcessTaskBll.java
PROJECT.CYCLE com.companyname.cycle.test.bll MockCycleBll.java
PROJECT.CYCLE com.companyname.pas.cycle.bll DasCycleBll.java
PROJECT.CYCLE com.companyname.pas.cycle.dal DasCycleDal.java
PROJECT.SHARED com.companyname.extensibility NamedExtensionPoint.java
PROJECT.SHARED com.companyname.extensibility PrePostExtensionPoint.java
PROJECT.SHARED com.companyname.extensibility.helper ExtensionConfigurationHelper.java
PROJECT.SRE com.companyname.ext DocumentGeneratorExt.java
PROJECT.SRE com.companyname.ext NamedExtensionPoint.java
PROJECT.SRE com.companyname.ext SystemDateBll.java
MODULE.CYCLE com.companyname.extensibility FileCycle1.java
MODULE.CYCLE com.companyname.extensibility FileCycle2.java

这似乎正是提问者在另一个问题中想要的结果。

所以问题在于需要对每个 $revno 循环执行 Perl 代码的主体。

foreach my $revno (@ARGV)   {
        print $revno, "\n";
}

编辑 将代码的主体按模块分组改为...

my %info;
while(<SVN>) {
    chomp;
    if ( /^\s+\S\s\/([^\/]+\/[^\/]+).*[^\/]$/ ) {
        (my $tag = $1) =~ s!/!.!g;
        s!.*/src/main/java/!!;
        my @a =  split(/\//);
        my $file = pop @a;
        print $tag, " ",  join(".", @a), " ",  $file, "\n";
        push @{$info{$tag}}, join(" ", join(".", @a), $file);
        #push @{$info{$tag}}, $file;
    }
}

while ( my ($key, $value) = each %info )
{
    print "$key\n";
    for my $line ( @{$info{$key}} ) {
        print "\t", $line, "\n";
    }
}

在之前给出的数据上会产生这个结果。

PROJECT.SHARED
    com.companyname.extensibility NamedExtensionPoint.java
    com.companyname.extensibility PrePostExtensionPoint.java
    com.companyname.extensibility.helper ExtensionConfigurationHelper.java
PROJECT.CYCLE
    com.companyname.cycle.agent Main.java
    com.companyname.cycle.agent.bll.tasks CycleGroupTask.java
    com.companyname.cycle.agent.bll.tasks CycleProcessTaskBll.java
    com.companyname.cycle.agent.bll.tasks CycleSequenceProcessTaskBll.java
    com.companyname.cycle.test.bll MockCycleBll.java
    com.companyname.pas.cycle.bll DasCycleBll.java
    com.companyname.pas.cycle.dal DasCycleDal.java
MODULE.CYCLE
    com.companyname.extensibility FileCycle1.java
    com.companyname.extensibility FileCycle2.java
PROJECT.SRE
    com.companyname.ext DocumentGeneratorExt.java
    com.companyname.ext NamedExtensionPoint.java
    com.companyname.ext SystemDateBll.java

这应该能在一定程度上帮助提问者实现他们想要的目标。

撰写回答