views:

215

answers:

2

I want to automate this process:

  1. A number comes from an external system, let's say 35.
  2. Search and find svn commits which have #35 in their comments on branch A.
  3. Make list of all the changes of these commits to the commits before them.
  4. Apply this changes to branch B.

For e.g. if rev 95 has #35 in its comments and introduced a new file over rev 94, add this [Add File x.txt]. And rev 132 has #35 in its comments and it changed a line in x.txt. Add this also [Change line n, file x.txt]. And so on. Now we have a list of changes:

[Add File x.txt]
[Change line n, file x.txt]
...

Apply this changes to branch B.

Can this be achieved on svn? What are the commands (or a way other than command line)? Does a documentation covering necessary commands for these operations exist out there?

+1  A: 

You need to know the revision(s) that was just committed, then checkout/switch to branch B, and svn merge -c 123,125 if the revisions were 123 and 125.

See also SvnBook on merging

Sander Rijken
+1  A: 

If your developers are disciplined enough to always write the ticket number in the commit log message, you can use this Perl script which searches for revisions where the log message contains a specified word. First checkout a working copy of branch B, then inside the working copy, run

perl merge-ticket.pl searchWord sourceURL

specifying the ticket number and the repository URL for branch A. The script merges the matching revisions from branch A into the working copy.

# merge-ticket.pl
use strict;
use XML::Parser;

if ($#ARGV != 1) {
    die "usage: $0 searchWord sourceURL\n";
    exit 1;
}
my $searchWord = $ARGV[0];
my $sourceUrl = $ARGV[1];

my @revisions = ();

my $revision;
my $inMsg;
my $message;

sub startTag {
    my($parser, $tag, %attrs) = @_;

    if ($tag eq 'logentry') {
        $revision = $attrs{'revision'};
    } elsif ($tag eq 'msg') {
        $inMsg = 1;
        $message = '';
    }
}

sub endTag {
    my($parser, $tag) = @_;

    if ($tag eq 'msg') {
        $inMsg = 0;
        if ($message =~ /\b$searchWord\b/) {
            push(@revisions, $revision);
            print "$revision: $message\n";
        }
    }
}

sub characterData {
    my($parser, $data) = @_;

    if ($inMsg) {
        $message .= $data;
    }
}

# Search commit log messages for word.
my $command = "svn log --xml $sourceUrl";
open(INPUT, "$command|") || die "Error executing $command: $!\n";
my $parser = new XML::Parser(
        Handlers => {
            Start => \&startTag,
            End => \&endTag,
            Char => \&characterData});
$parser->parse(*INPUT);
close(INPUT);

if ($#revisions < 0) {
    print "No log messages containing $searchWord found\n";
    exit 1;
}

# Merge found revisions into working copy.
my $changes = join(',', reverse(@revisions));
$command = "svn merge -c$changes $sourceUrl";
print "$command\n";
system $command;
Jim Huang
Wow, that looks like an awesome piece of work and does exactly what I need. If only I knew a little Perl (: I'll try to understand and convert this to c#. Thanks.
Serhat Özgel