| Revision 52 (by dpavlin, 2007/08/22 21:40:56) |
skip files which have empty line in to list (doesn't really work for all cases...)
|
#!/usr/bin/perl
use strict;
use warnings;
use SVN::Dump;
use Shell qw/svnadmin cp find svn rm/;
use Cwd qw/abs_path/;
use Data::Dump qw/dump/;
my $base = shift @ARGV;
$base ||= 'svn/';
my $checkout = "$base/checkout";
my $to_dump = 0;
die "usage: $0 temp-base-directory (default: $base)\n" unless ( -e $base );
my $mode = 'move';
my ( $from, $to ) = ( "$base/from", "$base/to/" );
my ( $from_list, $to_list ) = ( "$base/from.lst", "$base/to.lst" );
sub rep_url {
return 'file:///' . abs_path(shift);
}
sub create_list {
my ( $dir, $path ) = @_;
my $list = svn('ls', '-R', rep_url($from));
open(my $fh, '>', $path) || die "can't create $path: $!";
print $fh $list;
close($fh);
if ( ! -s $path ) {
unlink($path);
die "ABORT: created zero size $path\n";
}
warn "created: $path ", -s $path, "bytes\n";
}
die "please copy repository on which to perfrom operation to $from\n" if ( ! -e $from );
warn "##> collect all paths from repository $from\n";
create_list( $from, $from_list );
if ( ! -e $to_list ) {
cp( $from_list, $to_list );
die "created $to_list\nplease edit it to reflect new layout\n";
}
my $map;
my $mkdir;
open(my $fh_from, '<', $from_list ) || die "can't open $from_list: $!";
open(my $fh_to, '<', $to_list ) || die "can't open $to_list: $!";
while( my $path_from = <$fh_from> ) {
chomp($path_from);
my $path_to = <$fh_to> || die "list shorter, probably corrupt: $to_list\n";
chomp($path_to);
$map->{$path_from} = $path_to;
if ( $path_to =~ m{^(.+)/\Q$path_from\E$}) {
if ( ! $mkdir->{$1} ) {
$mkdir->{$1}++;
warn "##> will create $1 in new layout\n";
}
}
}
sub remap {
my ($path,$kind) = @_;
$path =~ s|/*$|/| if $kind && $kind eq 'dir';
if (defined( $map->{$path} )) {
my $to = $map->{$path};
warn "##> $path -> $to\n";
return $to;
} else {
warn "??> '$path'\n" if $path;
return $path;
}
}
warn "map = ",dump( $map ),$/;
warn "mkdir = ", dump( $mkdir ),$/;
if ( -e $to ) {
#die "$to allready exists! remove it to re-create repository\n";
rm('-Rf',$to);
}
svnadmin('create', $to);
open(my $fh_in, '-|', "svnadmin dump $from") || die "can't dump $from: $!";
open(my $fh_out, '|-', "svnadmin load $to") || die "can't load $to: $!";
open($fh_out, '>', "$base/to.dump") || die "can't dump to $base/to.dump: $!" if $to_dump;
my $dump = SVN::Dump->new( { fh => $fh_in } );
warn "## converting subversion repository $from -> $to\n";
while ( my $rec = $dump->next_record() ) {
if ( $rec->type() eq 'revision' && $rec->get_header( 'Revision-number' ) == 1 && $mkdir ) {
# copy revision record
print $fh_out $rec->as_string();
# fetch dirs sorted by length
foreach my $dir ( sort { length($a) <=> length($b) } keys %$mkdir ) {
print $fh_out <<"__NODE_ADD_DIR__";
Node-path: $dir
Node-kind: dir
Node-action: add
Prop-content-length: 10
Content-length: 10
PROPS-END
__NODE_ADD_DIR__
warn "##> inserted mkdir $dir\n";
}
next;
}
my $path = $rec->get_header('Node-path');
my $kind = $rec->get_header('Node-kind');
if ( $path ) {
my $new_path = remap($path,$kind);
if ( $new_path eq '' ) {
warn "##> skipped $kind $path\n";
next;
}
$rec->set_header('Node-path', $new_path );
if ( $path = $rec->get_header('Node-copyfrom-path') ) {
$rec->set_header('Node-copyfrom-path', remap($path,$kind) );
}
}
print $fh_out $rec->as_string();
}
if ($@) {
warn "ERROR: $@\n";
warn "##> content imported into $to\n";
svn('ls','-R', rep_url($to));
}
close($fh_in);
close($fh_out);
if ( $to_dump ) {
svnadmin('verify',$to);
} else {
rm('-Rf', $checkout) if -e $checkout;
svn('co', rep_url($to), $checkout);
}