-sub svn_log_xml {
- my (@log_args) = @_;
- my $log_fh = IO::File->new_tmpfile or croak $!;
-
- my $pid = fork;
- defined $pid or croak $!;
-
- if ($pid == 0) {
- open STDOUT, '>&', $log_fh or croak $!;
- exec (qw(svn log --xml), @log_args) or croak $!
- }
-
- waitpid $pid, 0;
- croak $? if $?;
-
- seek $log_fh, 0, 0;
- my @svn_log;
- my $log = XML::Simple::XMLin( $log_fh,
- ForceArray => ['path','revision','logentry'],
- KeepRoot => 0,
- KeyAttr => { logentry => '+revision',
- paths => '+path' },
- )->{logentry};
- foreach my $r (sort {$a <=> $b} keys %$log) {
- my $log_msg = $log->{$r};
- my ($Y,$m,$d,$H,$M,$S) = ($log_msg->{date} =~
- /(\d{4})\-(\d\d)\-(\d\d)T
- (\d\d)\:(\d\d)\:(\d\d)\.\d+Z$/x)
- or croak "Failed to parse date: ",
- $log->{$r}->{date};
- $log_msg->{date} = "+0000 $Y-$m-$d $H:$M:$S";
-
- # XML::Simple can't handle <msg></msg> as a string:
- if (ref $log_msg->{msg} eq 'HASH') {
- $log_msg->{msg} = "\n";
- } else {
- $log_msg->{msg} .= "\n";
- }
- push @svn_log, $log->{$r};
- }
- return \@svn_log;
-}
-