a) SHARE of an orphaned item can become a MOVE instead.

I did some work on this also. The actual patch for it was rather simple, but I had to change the MOVE handler also. Traditionally the move handler had a "twisted syntax". While all other handlers have the specification that the "parentphys" is the TARGET parent, while the "info" is the SOURCE parent. This was different for the MOVE handler. Here the parentphys was the move source and the info field the move target. This made it already difficult, since we had to switch the two fields sometimes in between. Now I came across the same problem again for the share handling and decided to fix this old behavior. While doing this I found a few places, where the MOVE handler could improve, and I still have a few unclear points. Esp. I don't know what the "# Don't know from where to move. Share it there instead" code in the ActionHandler::_move_handler should do. Since I didn't used MOVE very much, could somebody please check, whether the new MOVE behavior is still working?

the patch is for the latests revision.

Best regards
Dirk
Index: vss2svn.pl
===================================================================
--- vss2svn.pl  (revision 298)
+++ vss2svn.pl  (working copy)
@@ -611,49 +611,61 @@
     $rows = $sth->fetchall_arrayref( {} );
 
     my($childrecs, $child, $id);
-    my @delchild = ();
 
     foreach $row (@$rows) {
-        $row->{actiontype} = 'MOVE';
+        $row->{actiontype} = 'MOVE_TO';
         $childrecs = &GetChildRecs($row, 1);
 
+        my $source = undef;
+        my $target = $row->{parentphys};
+
         if (scalar @$childrecs > 1) {
-            &ThrowWarning("Multiple chidl recs for parent MOVE rec "
+            &ThrowWarning("Multiple child recs for parent MOVE rec "
                           . "'$row->{action_id}'");
         }
 
-        foreach $child (@$childrecs) {
-            my $update;
-            $update = $gCfg{dbh}->prepare('UPDATE PhysicalAction SET info = ?'
-                                          . 'WHERE action_id = ?');
-            
-            $update->execute( $row->{parentphys}, $child->{action_id} );
+        if (scalar @$childrecs >= 1) {
+            # only merge MOVE records that have the same timestamp
+            if ($row->{timestamp} == @$childrecs[0]->{timestamp}) {
+                $source = @$childrecs[0]->{parentphys};
+                &DeleteChildRec(@$childrecs[0]->{action_id});
+            }
         }
-
-        if (scalar @$childrecs == 0) {
-            my $sql = <<"EOSQL";
+        
+        my $sql = <<"EOSQL";
 UPDATE
     PhysicalAction
 SET
+    actiontype = 'MOVE',
     parentphys = ?,
-    actiontype = 'MOVE',
     info = ?
 WHERE
     action_id = ?
 EOSQL
-            my $update;
-            $update = $gCfg{dbh}->prepare($sql);
-            $update->execute( undef, $row->{parentphys},
-            $row->{action_id});
-        } else {
-            push(@delchild, $row->{action_id});
-        }
+        my $update;
+        $update = $gCfg{dbh}->prepare($sql);
+        
+        $update->execute( $target, $source, $row->{action_id});
     }
 
-    foreach $id (@delchild) {
-        &DeleteChildRec($id);
+
+    # change all remaining MOVE_TO records into MOVE records and swap the src 
and target
+    $sth = $gCfg{dbh}->prepare('SELECT * FROM PhysicalAction '
+                               . 'WHERE actiontype = "MOVE_TO"');
+    $sth->execute();
+    $rows = $sth->fetchall_arrayref( {} );
+
+    foreach $row (@$rows) {
+        my $update;
+        $update = $gCfg{dbh}->prepare('UPDATE PhysicalAction SET '
+                                      . 'actiontype = "MOVE", '
+                                      . 'parentphys = ?, '
+                                      . 'info = ? '
+                                      . 'WHERE action_id = ?');
+        $update->execute($row->{info}, $row->{parentphys}, $row->{action_id});
     }
 
+
     1;
 
 }  #  End MergeMoveData
@@ -764,7 +776,7 @@
         # May contain add'l info for the action depending on type:
         # RENAME: the new name (without path)
         # SHARE: the source path which was shared
-        # MOVE: the new path
+        # MOVE: the old path
         # PIN: the path of the version that was pinned      
         # LABEL: the name of the label
         $row->{info} = $handler->{info};
@@ -1333,7 +1345,7 @@
         AddedProject => {type => 1, action => 'ADD'},
         RestoredProject => {type => 1, action => 'RESTOREDPROJECT'},
         RenamedProject => {type => 1, action => 'RENAME'},
-        MovedProjectTo => {type => 1, action => 'MOVE'},
+        MovedProjectTo => {type => 1, action => 'MOVE_TO'},
         MovedProjectFrom => {type => 1, action => 'MOVE_FROM'},
         DeletedProject => {type => 1, action => 'DELETE'},
         DestroyedProject => {type => 1, action => 'DELETE'},
Index: Vss2Svn/ActionHandler.pm
===================================================================
--- Vss2Svn/ActionHandler.pm    (revision 298)
+++ Vss2Svn/ActionHandler.pm    (working copy)
@@ -251,13 +251,6 @@
         return 0;
     }
 
-#    # if this is not a share+pin action, then add this item to the sharedphys
-#    # list. Otherwise, this item is pinned to a specific version and does not
-#    # participate in shared actions
-#    if (!defined $row->{version}) {
-#        push @{ $physinfo->{sharedphys} }, $row->{parentphys};
-#    }
-    
     my $version = $row->{version};
     $version = $physinfo->{last_version} if (!defined $version);
 
@@ -283,13 +276,23 @@
 #        return $self->_add_handler();
     }
 
+    # if this is a share from orphan, and not a share+pin action either, we 
can treat it as a move
+    elsif (!defined $row->{version} &&        # share+pin?
+           defined $physinfo->{orphaned}      # orphaned?
+#          scalar @{$physinfo->{order}} == 1  # only one parent?
+       ) {
+        $physinfo->{parents}->{'_' . $row->{physname}}->{deleted} = 1;
+        undef $physinfo->{orphaned};
+        $self->{action} = 'MOVE';
+    }
+    
     # track the addition of the new parent
     $self->_add_parent ($physname, $row->{parentphys});
     
     # if this is a share+pin action, then remember the pin version
     if (defined $row->{version}) {
         $physinfo->{parents}->{$row->{parentphys}}->{pinned} = $row->{version};
-    } 
+    }
 
     $self->{itempaths} = [$itempath];
     $self->{info} = $sourceinfo;
@@ -410,8 +413,6 @@
     my($self) = @_;
     my $row = $self->{row};
 
-    # Get the existing paths before the move; parent sub will get the new
-    # name
     my $physname = $row->{physname};
     my $physinfo = $gPhysInfo{$physname};
   
@@ -422,58 +423,61 @@
         return 0;
     }
 
-    if (!defined $row->{parentphys}) {
+    # row->{info} contains the source parent
+    # row->{parentphys} contains the target parent
+
+    # check the source path    
+    if (!defined $row->{info}) {
       # Check if this is an orphaned item
-      if (scalar @{$physinfo->{order}} == 1) {
-        $row->{parentphys} = $physinfo->{order}[0];
+      if (defined $physinfo->{orphaned}) {
+        $row->{info} = '_' . $physname;
+        undef $physinfo->{orphaned};
       } else {
         # Don't know from where to move. Share it there instead
-        $row->{parentphys} = $row->{info};
-        $row->{info} = undef;
         $self->{action} = 'SHARE';
         return $self->_share_handler();
       }
     }
 
     # '$sourceinfo' is the path for the old location (the move source);
-    my $parentpath = $self->_get_current_parent_path ();
-    my $sourceinfo = $parentpath . $physinfo->{name}; # $row->{itemname};
+    my $sourceparent = $self->_get_parent_path ($row->{info});
+    my $sourceinfo = $sourceparent . $row->{itemname};
 
-    if (!defined ($row->{info})) {
+
+    # check the target path
+    if (!defined ($row->{parentphys})) {
         # the target directory was destroyed, so there is no apropriate move
         # target information. Fall back to a move to the orphaned cache
-        $row->{info} = '_' . $row->{physname};
+        $physinfo->{orphaned} = 1;
+        $row->{parentphys} = '_' . $row->{physname};
     }
 
     # '$itempath' contains the move target path
-    my $itempath = $self->_get_parent_path ($row->{info}) . $row->{itemname};
+    my $parentpath = $self->_get_current_parent_path ();
+    my $itempath = $parentpath . $physinfo->{name}; # $row->{itemname};
 
-    if (!defined($parentpath)) {
+
+    if (!defined($sourceparent)) {
         # We can't figure out the path for the parent that this move came from,
         # so it was either destroyed or corrupted. That means that this isn't
         # a move anymore; it's a new add.
 
         $self->{action} = 'ADD';
-#        $self->{version} = $version;
-#        return $self->_add_handler();
-        
-        # we need to swap the source and the target path
-        $sourceinfo = $itempath;
-        undef $itempath;
+        undef $sourceinfo;
     }
     else {
         # set the old parent inactive
-        $physinfo->{parents}->{$row->{parentphys}}->{deleted} = 1;
+        $physinfo->{parents}->{$row->{info}}->{deleted} = 1;
     }
 
     # if the item mysteriously changed name during the move
     $physinfo->{name} = $row->{itemname};
 
     # track the addition of the new parent
-    $self->_add_parent ($physname, $row->{info});
+    $self->_add_parent ($physname, $row->{parentphys});
     
-    $self->{itempaths} = [$sourceinfo];
-    $self->{info} = $itempath;
+    $self->{itempaths} = [$itempath];
+    $self->{info} = $sourceinfo;
 
     # the move target is now also a valid "copy from" itempath
     $self->_track_item_path ($physname, $row->{parentphys}, 
$physinfo->{last_version}, $itempath);
@@ -745,11 +749,6 @@
         return undef;
     }
 
-    #todo: make the behavoir of orphaned file tracking configurable
-#    if ($physinfo->{orphaned}) {
-#        return undef;
-#    }
-
     $self->{physname_seen} .= "$physname, ";
 
     # In a move szenario, we can have one deleted and one active parent. We
@@ -878,12 +877,6 @@
         return undef;
     }
 
-    #todo: make the behavoir of orphaned file tracking configurable
-#    if ($physinfo->{orphaned})
-#    {
-#        return undef;
-#       }
-
     $self->{physname_seen} .= "$physname, ";
 
 #    my @pathstoget =
Index: Vss2Svn/Dumpfile.pm
===================================================================
--- Vss2Svn/Dumpfile.pm (revision 298)
+++ Vss2Svn/Dumpfile.pm (working copy)
@@ -385,41 +385,41 @@
 
     # moving in SVN is the same as renaming; add the new and delete the old
 
-    my $newpath = $data->{info};
+    my $oldpath = $data->{info};
 
-    if ($self->{repository}->exists ($newpath)) {
-        $self->add_error("Attempt to move item '$itempath' to '$newpath' at "
+    if ($self->{repository}->exists ($itempath)) {
+        $self->add_error("Attempt to move item '$oldpath' to '$itempath' at "
             . "revision $data->{revision_id}, but destination already exists: 
possibly "
             . "missing delete; skipping");
         return 0;
     }
 
-    if (!$self->{repository}->exists ($itempath)) {
-        $self->add_error("Attempt to move item '$itempath' to '$newpath' at "
+    if (!$self->{repository}->exists ($oldpath)) {
+        $self->add_error("Attempt to move item '$oldpath' to '$itempath' at "
             . "revision $data->{revision_id}, but source doesn't exists: 
possibly "
             . "missing recover; skipping");
         return 0;
     }
     
     my $node = Vss2Svn::Dumpfile::Node->new();
-    $node->set_initial_props($newpath, $data);
+    $node->set_initial_props($itempath, $data);
     $node->{action} = 'add';
 
     my($copyrev, $copypath);
 
     $copyrev = $data->{revision_id} - 1;
-    $copypath = $itempath;
+    $copypath = $oldpath;
 
     $node->{copyrev} = $copyrev;
     $node->{copypath} = $copypath;
 
     push @$nodes, $node;
 
-#    $self->track_modified($data->{physname}, $data->{revision_id}, $newpath);
-#    $self->track_version ($data->{physname}, $data->{version}, $newpath);
+#    $self->track_modified($data->{physname}, $data->{revision_id}, $itempath);
+#    $self->track_version ($data->{physname}, $data->{version}, $itempath);
 
     $node = Vss2Svn::Dumpfile::Node->new();
-    $node->set_initial_props($itempath, $data);
+    $node->set_initial_props($oldpath, $data);
     $node->{action} = 'delete';
     $node->{hideprops} = 1;
 
_______________________________________________
vss2svn-users mailing list
Project homepage:
http://www.pumacode.org/projects/vss2svn/
Subscribe/Unsubscribe/Admin:
http://lists.pumacode.org/mailman/listinfo/vss2svn-users-lists.pumacode.org
Mailing list web interface (with searchable archives):
http://dir.gmane.org/gmane.comp.version-control.subversion.vss2svn.user

Reply via email to