I also wanted to ask, whether you used the nightly build. There where some improvement with labels.

I see in your output, that you also have used moves. Could you please try the attached patch also? This improves move handling, but is untested.

In order to help you more, I need to have a look at the generated database files, or you try yourself to track the events in the VssAction file. Esp. what happend to the file in revision 4905 and what was the flow of events for this file before this revision. The revision to actionId mapping is in the SvnRevisionVssAction database file.

You can also send me the files in a private mail, so I can have a look.

Best regards
Dirk

Larson, Aaron (SWCOE) schrieb:
"D" == Dirk  <Dirk> writes:

D> First of all, before going into the details, did you run "analyze
D> -f -v4" on your database?  Probably you could also try a "-d" to
D> delete dead files.

I was told that the database had been analyzed.  Hard to say if that
is true or not.  I ran analyze -f, that generated a number of errors,
I ran -f -d, that fixed some, but I had to delete some files, then ran
analyze -f -d again, still showed bad files, so I ran it again (-f
-d).  The last time the analyze log file only showed one interesting
line:

  There is a diff chain size mismatch in file 'RequirementsStatus.txt'
  at version 171 (versions earlier than that version can no longer be
  retrieved from the database.

Ok, so I ran vss2svn again, and the output log looks very similar to
what I previously posted.  The svnadmin load generated the same error
message, but with a very slightly different revision (previously it
was '4096-1'):

  svnadmin: File not found: transaction '4905-1', path
'labels/..../tpk242/tpk_TestFile.dat'

Which is the same file it previously died on.

D> It seems, that you have a few broken physical files in your
D> database, that can lead to a lot of problematic situations, since
D> part of the history is lost.

D> Debugging this will be a nightmare, but could help in order to
D> stabilize the code to deal with almost all worst situations.

I'm willing to spend some time debugging this, but its not *critical*
to our operations (we can continue to use read only VSS for these
legacy files), so I don't want to spend other folks time unless it
would be generally helpful.  On the other hand, it would be *useful*
to us, hence my willingness to debug.

_______________________________________________
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




Index: vss2svn.pl
===================================================================
--- vss2svn.pl  (revision 300)
+++ 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 300)
+++ 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 =
@@ -1169,9 +1162,7 @@
     my($self, $physname, $parentphys, $version, $deleted) = @_;
 
     my $physinfo = $gPhysInfo{$physname};
-    if (!defined $physinfo) {
-        return undef;
-    }
+ 
     # 1. check the parent requested, if there was an item name for this version
     #    we can use this item name, since it was valid in that time
     my $parent = $physinfo->{parents}->{$parentphys};
Index: Vss2Svn/Dumpfile.pm
===================================================================
--- Vss2Svn/Dumpfile.pm (revision 300)
+++ Vss2Svn/Dumpfile.pm (working copy)
@@ -385,44 +385,50 @@
 
     # 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);
+    # the new move target is a valid path.
+    $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;
 
+#   Deleted tracking is only necessary to be able to recover the item. But a 
move
+#   does not set a recover point, so we don't need to track the delete here. 
Additionally
+#   we do not have enough information for this operation.
+#   $self->track_deleted($data->{oldparentphys}, $data->{physname},
+#                        $data->{revision_id}, $oldpath);
+
     push @$nodes, $node;
 
 }  #  End _move_handler
@@ -559,7 +565,7 @@
     # as a valid share source.
     if (defined ($label)) {
         $label =~ s:/:_:g;
-    
+        
         my $vssitempath = $itempath;
         $vssitempath =~ s/^$main::gCfg{trunkdir}//;
         my $labelpath = "$main::gCfg{labeldir}/$label$vssitempath";
_______________________________________________
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