Greetings,

I tried to use the vss2svn 0.10 Beta 2 release to convert an old
repository. Didn't work. Among other things it contained 6 restore
points from older repositories...

Ah well, I couldn't get anything to compile on Windows so I zipped up the repository and began working on a 450MHz Fedora Core 4 box. After a week or two of learning Perl and hacking around, I finally got something produced that actually could be fed to svnadmin load without errors.

I've attached a patch in case someone else finds it useful.

Cheers,
/Micke

By the way, there seems to be a problem in the build process: On Windows
it looks for an output executable SSPHYS and on linux it searches for
SSPHYS.EXE, neither seem to be appropriate.





Index: vss2svn.pl
===================================================================
--- vss2svn.pl  (revision 223)
+++ vss2svn.pl  (working copy)
@@ -23,6 +23,10 @@
 
 our $VERSION = '0.10';
 
+our $ORPHAN_FOLDER = 0;
+our $ORPHAN_FOLDER_TIMESTAMP = 0;
+our %ORPHANS;
+
 &Initialize;
 &ConnectDatabase;
 
@@ -198,9 +202,184 @@
 
     $cache->commit();
 
+    my $cache2 = $cache->MakeContinuation();
+    AddOrphanAdds($cache2);
+    if ($ORPHAN_FOLDER) {
+       $cache2->commit();
+       $cache2 = $cache2->MakeContinuation();
+       AddOrphanBranches($cache2);
+       $cache2->commit();
+    }
+
 }  #  End GetPhysVssHistory
 
 ###############################################################################
+# AddOrphanAdds
+###############################################################################
+sub AddOrphanAdds {
+    my($cache) = @_;
+
+    my @cmds = ( 'ADD' ); #, 'BRANCH' );
+
+    foreach my $cmd (@cmds) {
+       print "Adding extra $cmd entries for orphan objects...\n";
+
+       my $sql1 = "SELECT * FROM Physical";
+       my $sth1 = $gCfg{dbh}->prepare($sql1);
+       $sth1->execute();
+       my $rows = $sth1->fetchall_arrayref( {} );
+
+NID:
+       foreach my $row1 (@$rows) {
+#    while (defined(my $row1 = $sth1->fetchrow_hashref() )) {
+           my $physname = $row1->{physname};
+           next NID if (uc($physname) eq 'AAAAAAAA');
+           my $sql2 = <<"EOSQL";
+SELECT
+    *
+FROM
+    PhysicalAction
+WHERE
+    physname = ?
+    AND actiontype = ?
+EOSQL
+
+            my $sth2 = $gCfg{dbh}->prepare($sql2);
+           $sth2->execute($physname, $cmd);
+
+           my $parent_found = 0;
+           my $any_row = 0;
+           my $itemname;
+           my $itemtype;
+           my $timestamp;
+           my $author;
+           my $is_binary;
+           my $info;
+           my $priority;
+           my $sortkey;
+           my $comment;
+       
+ROW:
+           while (defined(my $row2 = $sth2->fetchrow_hashref() )) {
+#              print "Testing $row2->{physname}\n" if $gCfg{verbose};
+               if (!$any_row) {
+                   $itemname = $row2->{itemname};
+                   $itemtype = $row2->{itemtype};
+                   $timestamp = $row2->{timestamp};
+                   $author = $row2->{author};
+                   $is_binary = $row2->{is_binary};
+                   $info = $row2->{info};
+                   $priority = $row2->{priority};
+                   $sortkey = $row2->{sortkey};
+                   $comment = $row2->{comment};
+                   $any_row = 1;
+               }
+               next ROW if (!defined($row2->{parentphys}));
+               $parent_found = 1;
+               last ROW;
+           }
+           if ($any_row && !$parent_found) {
+               # Project dangling in mid-air.  Create snake-oil folders...
+               if (!$ORPHAN_FOLDER) {
+                   $ORPHAN_FOLDER = 'AAAAAAAZ';
+               } else {
+                   if (!$ORPHAN_FOLDER_TIMESTAMP) {
+                       $ORPHAN_FOLDER_TIMESTAMP = $timestamp;
+                   }
+                   if ($timestamp < $ORPHAN_FOLDER_TIMESTAMP) {
+                       $ORPHAN_FOLDER_TIMESTAMP = $timestamp;
+                   }
+               }
+               print "Creating orphan $cmd for $physname\n" if $gCfg{verbose};
+               my $snakeoil = uc($physname);
+               $snakeoil =~ s/A$/Z/;
+               if (!exists $ORPHANS{$physname}) {
+                   $ORPHANS{$physname} = $snakeoil;
+                   my $sortkey2 = reverse($snakeoil);
+                   $cache->add($snakeoil, undef, $ORPHAN_FOLDER, 'ADD',
+                               $physname.'/', 1, $timestamp, 'Admin',
+                               0, undef, 0, $sortkey2,
+                               0, $comment);
+               }
+               $cache->add($physname, undef, $snakeoil,
+                           $cmd, $itemname,
+                           $itemtype, $timestamp,
+                           $author, $is_binary,
+                           $info, $priority,
+                           $sortkey, 1, $comment);
+           }
+       }
+    }
+
+    if ($ORPHAN_FOLDER) {
+       # Projects dangling in mid-air.  Create snake-oil root folder...
+       my $skey = reverse($ORPHAN_FOLDER);
+       $cache->add($ORPHAN_FOLDER, undef, 'AAAAAAAA', 'ADD',
+                   'vss2svn_orphans/', 1, $ORPHAN_FOLDER_TIMESTAMP, 'Admin',
+                   0, undef, 0, $skey,
+                   0, "Folder created for all vss2svn orphans");
+    }
+
+}  #  End AddOrphanAdds
+
+###############################################################################
+# AddOrphanBranches
+###############################################################################
+sub AddOrphanBranches {
+    my($cache) = @_;
+
+    print "Adding extra BRANCH entries for branched orphan objects...\n";
+
+    
+    my %items;
+    my %added = %ORPHANS;
+
+    while (%added) {
+       %items = %added;
+       %added = ();
+       my($iid, $did);
+       while (($iid, $did) = each %items) {
+           my($sth, $row);
+           my $sql = <<"EOSQL";
+SELECT
+    *
+FROM
+    PhysicalAction
+WHERE
+    info = ?
+    AND parentdata = 0
+    AND actiontype = 'BRANCH'
+    AND parentphys IS NULL
+EOSQL
+
+            $sth = $gCfg{dbh}->prepare($sql);
+           $sth->execute($iid);
+ROW:
+           while (defined($row = $sth->fetchrow_hashref() )) {
+               next ROW if (defined($row->{parentphys}));
+               # Found a branch parent record for an orphan item (without
+               # a proper parent).
+               print "Creating orphan BRANCH parent for $iid\n" if 
$gCfg{verbose};
+               my $pn = $row->{physname};
+               $cache->add($pn, undef, $did,
+                           'BRANCH', $row->{itemname},
+                           $row->{itemtype}, $row->{timestamp},
+                           $row->{author}, $row->{is_binary}, $row->{info},
+                           $row->{priority}, $row->{sortkey}, 1,
+                           $row->{comment});
+               # This branch was done on an orphan item. This item must
+               # also be an orphaned item in the same locaion
+               if (!exists $ORPHANS{$pn}) {
+                   $ORPHANS{$pn} = $did;
+                   $added{$pn} = $did;
+               }
+           }
+       }
+    }
+
+}  #  End AddOrphanBranches
+
+###############################################################################
 #  FindPhysnameFile
 ###############################################################################
 sub FindPhysnameFile {
@@ -322,7 +501,7 @@
         $is_binary = 0;
         $info = undef;
         $parentdata = 0;
-        $priority = 5;
+        $priority = 6;
 
         if ($version->{Comment} && !ref($version->{Comment})) {
             $comment = $version->{Comment} || undef;
@@ -372,6 +551,12 @@
             $is_binary = 1;
         }
 
+       if ($actiontype eq 'RESTORE') {
+           # Restored project...
+           print "Restore of $tphysname in $parentphys\n" if $gCfg{verbose};
+           $actiontype = 'MOVE';
+       }
+
         if ($actiontype eq 'RENAME') {
             # if a rename, we store the new name in the action's 'info' field
 
@@ -590,14 +775,13 @@
     my($sth, $row, $action, $handler, $physinfo, $itempaths, $allitempaths);
 
     my $sql = 'SELECT * FROM PhysicalAction ORDER BY timestamp ASC, '
-                    . 'priority ASC, sortkey ASC';
+                   . 'itemtype ASC, priority ASC, sortkey ASC';
 
     $sth = $gCfg{dbh}->prepare($sql);
     $sth->execute();
 
 ROW:
     while(defined($row = $sth->fetchrow_hashref() )) {
-        $svnrevs->check($row);
         $action = $row->{actiontype};
 
         $handler = Vss2Svn::ActionHandler->new($row);
@@ -646,6 +830,8 @@
             }
         }
 
+        $svnrevs->check($row);
+
         # May contain add'l info for the action depending on type:
         # RENAME: the new name (without path)
         # SHARE: the source path which was shared
@@ -1191,6 +1377,7 @@
         DeletedProject => {type => 1, action => 'DELETE'},
         DestroyedProject => {type => 1, action => 'DELETE'},
         RecoveredProject => {type => 1, action => 'RECOVER'},
+       Restore => {type => 1, action => 'RESTORE'},
         CheckedIn => {type => 2, action => 'COMMIT'},
         CreatedFile => {type => 2, action => 'ADD'},
         AddedFile => {type => 2, action => 'ADD'},
Index: Vss2Svn/ActionHandler.pm
===================================================================
--- Vss2Svn/ActionHandler.pm    (revision 223)
+++ Vss2Svn/ActionHandler.pm    (working copy)
@@ -103,6 +103,16 @@
          sharedphys => [],
         };
 
+    if (!defined $row->{itemname} || $row->{itemname} eq '') {
+        $self->{errmsg} .= "Attempt to add unnamed entry '$row->{physname}'\n";
+        return 0;
+    }
+
+    if (uc($row->{physname}) eq 'AAAAAAAA') {
+       # The root is already there in Subversion, right?
+       return 0;
+    }
+
     # File was just created so no need to look for shares
     $self->{itempaths} = $self->_get_current_item_paths(1);
 
@@ -180,9 +190,19 @@
     # 'info' contains the source path
     my $parentpaths = $self->_get_item_paths($row->{parentphys}, 1);
 
+    # Silly 'the bloody name changed' test
+    if ($physinfo->{name} ne $row->{itemname}) {
+       warn "Shared name not same: $physinfo->{name} ne $row->{itemname}\n";
+    }
+
     $self->{itempaths} = [$parentpaths->[0] . $physinfo->{name}];
     my $sourceinfo = $self->_get_current_item_paths(1);
 
+    if (!defined $physinfo->{name} || $physinfo->{name} eq '') {
+        $self->{errmsg} .= "Attempt to share unnamed entry 
'$row->{physname}'\n";
+        return 0;
+    }
+
     if (!defined($sourceinfo) || scalar(@$sourceinfo) == 0) {
         # We can't figure out the path for the parent that this share came 
from,
         # so it was either destroyed or corrupted. That means that this isn't
@@ -234,11 +254,16 @@
     $gPhysInfo{$physname} =
         {
          type       => $row->{itemtype},
-         name       => $row->{itemname},
+         name       => $oldphysinfo->{name}, # $row->{itemname},
          parentphys => $row->{parentphys},
          sharedphys => [],
         };
 
+    if (!defined $row->{itemname} || $row->{itemname} eq '') {
+        $self->{errmsg} .= "Attempt to branch unnamed entry 
'$row->{physname}'\n";
+        return 0;
+    }
+
     $self->{itempaths} = $self->_get_current_item_paths(1);
 
     return 1;
@@ -270,6 +295,11 @@
     # we don't need to worry about any shared paths
     $physinfo->{parentphys} = $row->{parentphys};
 
+    if (!defined $physinfo->{name} || $physinfo->{name} eq '') {
+        $self->{errmsg} .= "Attempt to move unnamed entry 
'$row->{physname}'\n";
+        return 0;
+    }
+
     # 'itempaths' has the original path; 'info' has the new
     $self->{itempaths} = $itempaths;
     $self->{info} = $self->_get_current_item_paths(1)->[0];
@@ -330,6 +360,11 @@
         $physinfo->{sharedphys} = $sharedphys;
     }
 
+    if (!defined $physinfo->{name} || $physinfo->{name} eq '') {
+        $self->{errmsg} .= "Attempt to delete unnamed entry 
'$row->{physname}'\n";
+        return 0;
+    }
+
     $self->{itempaths} = $itempaths;
 
     return 1;
@@ -365,6 +400,11 @@
         $physinfo->{parentphys} = $row->{parentphys};
     }
 
+    if (!defined $physinfo->{name} || $physinfo->{name} eq '') {
+        $self->{errmsg} .= "Attempt to recover unnamed entry 
'$row->{physname}'\n";
+        return 0;
+    }
+
     # We only recover the path explicitly set in this row, so build the path
     # ourself by taking the path of this parent and appending the name
     my $parentpaths = $self->_get_item_paths($row->{parentphys}, 1);
@@ -457,9 +497,11 @@
     # return just one, but sometimes one of the paths becomes corrupted so we
     # take the first one we can get.
     if ($mainonly && @$paths) {
+#      print join(" + ", @$paths) . "\n";
         return [ $paths->[0] ];
     }
 
+#    print "*" . join(" + ", @$paths) . "\n";
     return $paths;
 
 }  #  End _get_item_paths
Index: Vss2Svn/DataCache.pm
===================================================================
--- Vss2Svn/DataCache.pm        (revision 223)
+++ Vss2Svn/DataCache.pm        (working copy)
@@ -24,7 +24,7 @@
          pkey => -1,
          verbose => $gCfg{verbose},
          fh => undef,
-         file => "$gCfg{cachedir}\\datachache.$table.tmp.txt",
+         file => "$gCfg{cachedir}/datacache.$table.tmp.txt",
         };
 
     $self = bless($self, $class);
@@ -138,5 +138,26 @@
     $gCfg{verbose} = $verbose;
 }  #  End SetVerbose
 
+###############################################################################
+#  MakeContinuation
+###############################################################################
+sub MakeContinuation {
+    my($self) = @_;
 
-1;
\ No newline at end of file
+    $self->{file} = 
"$gCfg{cachedir}/datacache.$self->{table}.tmp-$self->{pkey}.txt";
+
+    if ((-e $self->{file}) && !(unlink($self->{file}))) {
+        print "\nERROR: Could not delete existing cache file 
'$self->{file}'\n";
+        return undef;
+    }
+
+    if ( !open($self->{fh}, ">$self->{file}") ) {
+        print "\nERROR: Could not open file '$self->{file}'\n";
+        return undef;
+    }
+   
+    return $self;
+}  #  End MakeContinuation
+
+
+1;
Index: Vss2Svn/Dumpfile.pm
===================================================================
--- Vss2Svn/Dumpfile.pm (revision 223)
+++ Vss2Svn/Dumpfile.pm (working copy)
@@ -728,7 +728,7 @@
         return 0;
     }
 
-    my $file = "$expdir\\$data->{physname}.$data->{version}";
+    my $file = "$expdir/$data->{physname}.$data->{version}";
 
     if (!open EXP, "$file") {
         $self->add_error("Could not open export file '$file'");


_______________________________________________
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