--- trunk/svndump-move.pl 2007/08/03 18:13:55 49 +++ trunk/svndump-move.pl 2007/08/03 21:50:54 50 @@ -4,19 +4,28 @@ 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 ( $fl, $tl ) = ( "$base/from.lst", "$base/to.lst" ); +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', 'file://' . abs_path($from)); + my $list = svn('ls', '-R', rep_url($from)); open(my $fh, '>', $path) || die "can't create $path: $!"; print $fh $list; close($fh); @@ -29,25 +38,48 @@ 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, $fl ); +warn "##> collect all paths from repository $from\n"; +create_list( $from, $from_list ); -if ( ! -e $tl ) { - cp( $fl, $tl ); - die "created $tl\nplease edit it to reflect new layout\n"; +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"; + } + } +} -open(my $fhf, '<', $fl ) || die "can't open $fl: $!"; -open(my $fht, '<', $tl ) || die "can't open $tl: $!"; -while( my $lf = <$fhf> ) { - chomp($lf); - my $lt = <$fht> || die "list shorter, probably corrupt: $tl\n"; - chomp($lt); - $map->{$lf} = $lt; +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); @@ -56,24 +88,60 @@ 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 "## $from -> $to\n"; +warn "## converting subversion repository $from -> $to\n"; while ( my $rec = $dump->next_record() ) { - my $type = $rec->type(); - if ( $type eq 'revision' && $rec->get_header( 'Revision-number' ) != 0 ) { - my $to = 'dpavlin@rot13.org'; - $rec->set_property( 'svn:author' => $to ); + + 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'); - if ( $path && defined( $map->{$path} ) ) { - my $to = $map->{$path}; - warn "##> $path -> $to\n"; - $rec->set_header('Node-path', $to); + my $kind = $rec->get_header('Node-kind'); + if ( $path ) { + $rec->set_header('Node-path', remap($path,$kind) ); + 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); +}