I found a glitch in the Dumpfile::_move_handler. I forgot to track the
"new" move target as a valid item path. This was problematic in
situations, where the move target was used as a copy_from rev, e.g. in a
subsequent share.
Here is the full patch again
Dirk
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