[svk-commit] r2728 - trunk/lib/SVK/Mirror/Backend

nobody at bestpractical.com nobody at bestpractical.com
Thu Apr 17 01:44:38 EDT 2008


Author: clkao
Date: Thu Apr 17 01:44:37 2008
New Revision: 2728

Modified:
   trunk/lib/SVK/Mirror/Backend/SVNRa.pm

Log:
fix sync-rebase-multi.t for svn 1.5.


Modified: trunk/lib/SVK/Mirror/Backend/SVNRa.pm
==============================================================================
--- trunk/lib/SVK/Mirror/Backend/SVNRa.pm	(original)
+++ trunk/lib/SVK/Mirror/Backend/SVNRa.pm	Thu Apr 17 01:44:37 2008
@@ -603,25 +603,29 @@
 }
 
 sub _sync_edge_changeset {
-    my ($self, $revdata, $callback, $translate_from) = @_;
+    my ($self, $revdata, $callback, $translate_from, $up_to) = @_;
 
     my $paths = $revdata->[2];
     unless ($paths) {
         my $ra = $self->_new_ra;
 
         $ra->get_log([''], $revdata->[0], $revdata->[0], 0,
-                     1, 1, sub { $paths = shift; } );
+                     1, 1, sub { $paths = _dclone_log_change_paths(shift); } );
         $self->_ra_finished($ra);
     }
 
     my ($entry, $old_path, $old_rev) = $self->_find_edge_entry( $paths, $translate_from || $self->source_path ) or return;
-    my ($copyfrom_path, $copyfrom_rev) = ($entry->copyfrom_path, $entry->copyfrom_rev);
 
-    $self->_mirror_changesets( $revdata->[0], $callback, 0, $old_path );
+    my ($copyfrom_path, $copyfrom_rev) = ($entry->{copyfrom_path}, $entry->{copyfrom_rev});
+
+    if ($up_to) {
+        $self->_mirror_changesets_with_cross( $revdata->[0], $callback, 0, $old_path );
+    }
+
 
     my $ra = $self->_new_ra;
 
-    $ra->reparent( $self->source_root . $copyfrom_path );
+    $ra->reparent( $self->source_root . $old_path );
     $self->sync_changeset
         ( $revdata->[0], $revdata->[1], {},
           $callback,
@@ -632,7 +636,7 @@
               $editor = SVK::Editor::FilterProp->new
                   ( { cb_prop => sub { return $_[0] !~ m/^svn:(wc|entry)/; },
                       _editor => [ $editor ] } );
-              my $report = $ra->do_diff($revdata->[0], '', 1, 1, $self->source_root.$self->source_path, $editor);
+              my $report = $ra->do_diff($revdata->[0], '', 1, 1, $self->source_root.($translate_from || $self->source_path), $editor);
               $report->set_path('', $copyfrom_rev, 0, undef );
               $report->finish_report;
               if ( %{$txn->root->paths_changed} ) {
@@ -642,6 +646,13 @@
 
 }
 
+sub _sync_up_to_edge_changeset {
+    my ($self, $revdata, $callback) = @_;
+
+    return $self->_sync_edge_changeset($revdata, $callback, undef, 1);
+}
+
+
 sub _find_edge_entry {
     my ($self, $paths, $translate_from) = @_;
 
@@ -649,60 +660,102 @@
         if (Path::Class::Dir->new_foreign("Unix", $_)
             ->subsumes($translate_from)) {
             my $entry = $paths->{$_};
-            if ($entry->action eq 'A' && $entry->copyfrom_path) {
+            if ($entry->{action} eq 'A' && $entry->{copyfrom_path}) {
                 return ($entry,
-                        SVK::Util::abs2rel($translate_from, $_ => $entry->copyfrom_path),
-                        $entry->copyfrom_rev);
+                        SVK::Util::abs2rel($translate_from, $_ => $entry->{copyfrom_path}),
+                        $entry->{copyfrom_rev});
             }
         }
     }
     return;
 }
 
-sub _mirror_changesets {
+sub _dclone_log_change_paths {
+    my $p = shift or return;
+    my $paths = {};
+    for ( keys %$p ) {
+        $paths->{$_} = { action => $p->{$_}->action,
+            copyfrom_path => $p->{$_}->copyfrom_path,
+            copyfrom_rev  => $p->{$_}->copyfrom_rev,
+        };
+    }
+    return $paths;
+}
+
+# note this method doesn't actually sync $torev, it's dealing with all
+# the changes before it
+sub _mirror_changesets_with_cross {
     my ( $self, $torev, $callback, $fake_last, $translate_from ) = @_;
     my @revs;
-    my $cross = $translate_from ? 1 : 0;
-    $self->traverse_new_changesets( sub { push @revs, [@_] unless $fake_last && $torev && $_[0] == $torev}, $torev, $cross, $cross );
+    $self->traverse_new_changesets(
+        sub {
+            my $paths = _dclone_log_change_paths(pop);
+            push @revs, [ @_, $paths ]
+                unless $fake_last && $torev && $_[0] == $torev;
+        },
+        $torev, 1, 1 );
 
     # the last revision belongs to our caller, so don't sync it.
-    pop @revs if $cross;
+    pop @revs;
 
     return unless @revs;
-    if ($cross) {
-        # if we are in cross mode, our @revs might already contain
-        # renames that we need to segment with different
-        # translate_from
-        my $tmp_translate_from = $translate_from;
-        my (@batch, @newrev);
-        for (reverse @revs) {
-            my $paths = $_->[-1];
-            my ($entry, $old_path, $oldrev) = $self->_find_edge_entry($paths, $tmp_translate_from || $self->source_path);
-            unless ($entry) {
-                unshift @newrev, $_;
-                next;
-            }
 
-            unshift @batch, [\@newrev, $_, $old_path];
-            @newrev = ();
-            $tmp_translate_from = $old_path;
-        }
-        for (@batch) {
-            my ($revs, $edge, $t) = @$_;
-            $self->_sync_changesets($callback, $revs, $t);
-            $self->_sync_edge_changeset($edge, $callback, $_);
+    my @batch;
+
+    # if we are in cross mode, our @revs might already contain
+    # renames that we need to segment with different
+    # translate_from into different batches
+    my $tmp_translate_from = $translate_from || $self->source_path;
+    my (@newrev);
+    for ( reverse @revs ) {
+        my $paths = $_->[-1];
+        my ( $entry, $old_path, $oldrev ) = $self->_find_edge_entry( $paths, $tmp_translate_from );
+
+        # if there's no edge entry, it's the same batch
+        unless ($entry) {
+            unshift @newrev, $_;
+            next;
         }
 
+        push @batch, [ [@newrev], $_, $tmp_translate_from, $old_path ];
+        @newrev             = ();
+        $tmp_translate_from = $old_path;
+    }
+    @revs = @newrev;
+
+    $self->_sync_changesets($callback, \@revs, $tmp_translate_from);
+
+    for (@batch) {
+        my ($revs, $edge, $t, $ot) = @$_;
+        $self->_sync_edge_changeset($edge, $callback, $ot);
+        $self->_sync_changesets($callback, $revs, $t);
     }
-    # get the first revision and see if it's renamed from somewhere else
 
-    if ($self->mirror->follow_anchor_copy && !$cross) {
-        $self->_sync_edge_changeset(shift @revs, $callback, $translate_from);
-    }
 
-    $self->_sync_changesets($callback, \@revs, $translate_from);
+}
+
+sub _mirror_changesets {
+    my ( $self, $torev, $callback, $fake_last ) = @_;
+    my @revs;
+    $self->traverse_new_changesets(
+        sub {
+            my $paths = _dclone_log_change_paths(pop);
+            push @revs, [ @_, $paths ]
+                unless $fake_last && $torev && $_[0] == $torev;
+        },
+        $torev, 0, 0 );
+
+    return unless @revs;
+
+    # get the first revision and see if it's renamed from somewhere else
+    if ($self->mirror->follow_anchor_copy) {
+        $self->_sync_up_to_edge_changeset(shift @revs, $callback );
+    }
 
+    # the rest
+    $self->_sync_changesets($callback, \@revs);
 }
+
 sub _sync_changesets {
     my ($self, $callback, $revs, $translate_from) = @_;
 


More information about the svk-commit mailing list